Figură 2-1 Schema de principiu a instalației 12 [305186]

UNIVERSITATEA MARITIMĂ CONSTANȚA

FACULTATEA DE ELECTROMECANICĂ NAVALĂ

SPECIALIZAREA SISTEME ELECTRICE AVANSATE

LUCRARE DE DISERTAȚIE

Coordonator științific:

Conf. Univ. Dr. Ing. Mihaela HNATIUC

Absolvent: [anonimizat]

2017

UNIVERSITATEA MARITIMĂ CONSTANȚA

FACULTATEA DE ELECTROMECANICĂ NAVALĂ

SPECIALIZAREA SISTEME ELECTRICE AVANSATE

TITLUL LUCRARII:

Coordonator Științific:

Conf. Univ. Dr. Ing. Mihaela HNATIUC

Absolvent: [anonimizat]

2017

LISTA FIGURILOR

Figură 2-1 Schema de principiu a instalației 12

Figură 2-2 [anonimizat], boiler 15

Figură 2-3 Panou conexiuni si relee 15

Figură 2-4 Imagine de ansamblu a instalației 16

Figură 2-5 Debitmetru GICAR 9.0.96.02C 17

Figură 2-6 Localizarea debitmetrului de sub tancul de lapte nr.1 17

Figură 2-7 Pompa OSIP PB 50 18

Figură 2-8 Localizarea celor două pompe (de apă și cea de transfer) 18

Figură 2-9 Motor cu reductor pentru axul melcat 20

Figură 2-10 Șnec pentru transportul laptelui praf direct în mixer 20

Figură 2-11 Schema de principiu pentru transportul laptelui praf direct în mixer 21

Figură 2-12 Cotele șnecului 21

Figură 2-13 Recipietul pentru lapte praf și/sau aditivi 22

Figură 2-14 Pompe de dozare (vitamine, antibiotice) 23

Figură 2-15 Motorul mixerului și vasul pentru amestec 24

Figură 2-16 Relee MY4N 24

Figură 2-17 Relee MK3PN 26

Figură 2-18 Pinii microcontrolerului utilizat 29

Figură 2-19 Memoria program pentru controlerele dsPIC30F4011 34

Figură 2-20 Organizarea memoriei program 35

Figură 2-21 Harta memoriei de date pentru controlerele dsPIC30F4011 36

Figură 2-22 Accesarea memoriei program cu instructiuni tabel 38

Figură 2-23 Adresarea pentru registrele table 39

Figură 2-24 Diagrama bloc a sistemului Reset 40

Figură 2-25 Arhitectura DMA 43

Figură 2-26 Diagrama sistemului oscilator al controlerului dsPIC30F4011 44

Figură 2-27 Diagrama bloc a structurii unui port de intrare/iesire 45

Figură 2-28 Diagrama bloc a modulului timer 1 pe 16 biti 46

Figură 2-29 Diagrama bloc a modulului timer 2/3 pe 32 biti 47

Figură 2-30 Diagrama bloc a modului de captura a intrarii 48

Figură 2-31 Diagrama bloc a modulului ADC 49

Figură 2-32 Intrari si iesiri microcontroler 50

Figură 2-33 Conexiunea releelor și a electrovalvelor 53

Figură 2-34 [anonimizat] 54

Figură 2-35 Conexiunile releelor cu led de stare 55

Figură 2-36 Conexiunea debitmetrului 56

Figură 2-37 Conexiunea senzorului de temperatură 56

Figură 2-38 [anonimizat] 57

Figură 2-39 Modul RfID pentru identificarea vițeilor 57

Figură 2-40 Cablajul electronic 58

Figură 3-1 Interfața utilizatorului UI 59

Figură 3-2 Meniul „Diagnose” 61

Figură 3-3 Meniul „Settings” 62

Figură 3-4 Meniul „Alarms” 63

Figură 3-5 Fereastra cu lista de alarme și ID corespondent 64

Figură 3-6 Fereastra „Alarm Configuration” 65

Figură 3-7 Meniul “RfID Tags” 65

Figură 3-8 Stația de hrănire cu clapeta în pozitie acces permis la tetină 67

Figură 3-9 Stația de hranire. Detalii antena și clapeta 67

Figură 3-10 Meniul ”Calves Database” 68

Figură 3-11 Fereastra “Add Calf” 68

Figură 3-12 Fereastra ”Recipes” 69

LISTA TABELELOR

Tabel 2.1 Descrierea pinilor microcontrolerului dsPIC30F4011 30

Tabel 2.2 Descrierea pinilor microcontrolerului dsPIC30F4011 – continuare 31

Tabel 2.3 Tabelul vectorilor de intrerupere 41

Tabel 2.4 Acces DMA cu numarul cererii de intrerupere asociat 42

Tabel 2. 5 Definire intrări și ieșiri 50

INTRODUCERE

Sistemele automate pentru hrănirea vițeilor, controlate de calculator, sunt foarte căutate la nivel internațional datorită reducerii volumului de muncă fizică. Creșterea cantitativă și calitativă a productivității fermelor din zootehnie se poate face prin automatizarea unor procese simple, în acest caz alăptarea vițeilor. Acest sistem este alcătuit dintr-o unitate autonomă care încălzește apa și o amestecă cu o cantitate prescrisă de lapte praf, apoi se transferă într-un cilindru de sticlă de la care se poate hrăni vițelul prin intermediul unei stații de hrănire prevăzută cu tetine.

Am propus construirea unui sistem automat pentru hrănirea vițeilor ce conține un microcontroler, senzori, relee, pompe, mixer, interfața software, stație de alăptare. Construcția echipamentului de la zero, dintr-o perspectivă proprie și cu idei proprii ajutat de date provenite din studiile de profil și din alte surse, a ridicat o multitudine de probleme software, hardware și de execuție a acestora.

Avantajele acestui sistem automat sunt reprezentate de posibilitatea adaptării la ferme de orice dimensiuni prin introducerea de stații de hrănire suplimentare, de economia de timp si reducerea forței de muncă, de hrănirea cu lapte praf și/sau concentrate, de administrarea la temperatura constantă, de ore flexibile de hrănire, de identificarea vițeilor bolnavi și permite rețete individuale de hrănire în funcție de vârstă, rasa sau starea de sănătate a vițelului. De asemenea este un sistem robust având costuri de întreținere reduse (comparativ cu echipamentele oferite de concurență).

Este un sistem automat adaptabil, vițeii având posibilitatea de a se hrăni în ritmul lor natural, de mai multe ori în aceeași zi. Hrănirea se face într-o manieră controlată, având posibilitatea de a stabili numărul meselor și urmări cantitatea consumată de fiecare vițel prin identificarea acestora, mai exact a senzorului RfID. Toate rețetele de hrănire pot fi accesate din meniul software putându-se modifica manual cantitățile de dozare în funcție de recomandările furnizorului de lapte praf.

Pentru a nu se transmite bolile de la un vițel la altul, după fiecare hrănire are loc o spălare cu apă fierbinte urmată de o clătire a stației de alăptare.

În prima parte a lucrării este prezentat stadiul actual al sistemelor existente de hrănire artificială, urmat de descrierea sistemului, a părților componente, descrierea interfeței om-mașină (GUI) și concluzii.

Conceperea acestui sistem de hrănire automată a vițeilor mi-a permis să pun în aplicare cunoștințele dobândite anterior, iar realizarea acestui proiect s-a bazat pe cunoștințele acumulate în perioada de studiu postuniversitar.

STADIUL ACTUAL

Progresul tehnologic ce a atins toate domeniile de activitate nu putea rămâne fără impact în agricultură și zootehnie, mai ales ca urmare a creșterii exponențiale a populației globului și implicit a nevoii de hrană a populației. În țările dezvoltate odată cu creșterea cererii de produse alimentare s-a ajuns la situația în care agricultura și zootehnia tradiționale sa nu poată acoperii această cerere, de aici necesitatea apariției dezvoltării și tehnologizării acestui domeniu de activitate.

Rezultatul a fost creșterea producției, reducerea costurilor și a forței de muncă precum și o calitate mai ridicata a produselor. În zootehnie tehnologizarea și automatizarea fermelor de animale a permis creșterea productivității prin posibilitatea creșterii în condiții optime a unui număr mai mare de animale cu reducerea cazurilor de animale bolnave, precum și scăderea costurilor datorită reducerii pierderilor de furaje precum si cu privire la forța de munca, automatizările in zootehnie permițând îngrijirea unui număr mai mare de animale cu un număr mai mic de persoane angajate.

„In vederea aplicării unei alimentații raționale, este necesara cunoașterea nevoii de substanțe nutritive pentru fiecare specie si categorie de animale, aflate in diferite etape ale vieții. Cerințele de substanțe nutritive sunt exprimate prin normele de hrana, care reprezintă cantitatea substanțelor nutritive necesare unui animal, într-un interval de timp stabilit, pentru asigurarea funcțiilor vitale, dar si pentru obținerea ulterioara a producțiilor.”

Creșterea animalelor presupune hrănirea acestora prin aplicarea unei alimentații raționale care se bazează pe cunoașterea necesitaților nutriționale ale fiecărei specii si categorie de animal aflata in anumite stadii de dezvoltare. Alimentația raționala se bazează pe asigurarea normelor de hrana animalelor din ferme prin cunoașterea cantităților de substanțe nutritive necesare fiecărui animal într-un interval de timp stabilit. Norma de hrana nu numai ca asigura susținerea funcțiilor vitale ale animalului dar permite creșterea ulterioara a producției.

In fermele pentru creștere bovinelor pentru carne si lapte automatizările in domeniu au permis hrănirea vițeilor după prima săptămâna de viată prin alimentație artificiala care are ca avantaje o înțărcare mai timpurie, o dezvoltare armonioasa, scăderea riscului îmbolnăvirilor si nu in ultimul rând creșterea cantității de lapte ce poate fi dat spre consum populației sau valorificat.

Pentru vițeii neînțărcați, normele de hrana nu trebuie interpretate ca limite fixe, invariabile, acestea fiind adaptabile, prin conținut si cantitate. Una dintre piesele grele ale programelor de hrănire a vițeilor este, după alăptare, consumul de furaje concentrate, de buna calitate, cu palpabilitate ridicata, încă din prima săptămâna a vieții. Funcția de dezvoltare a rumenului va fi stimulata printr-un consum adecvat de concentrate, care va suplimenta necesarul de hrana al vițeilor, peste aportul asigurat prin dieta lichida. Se poate ajunge, astfel, mai devreme la înțărcare, furnizând nutrimente la un cost mai redus decât laptele sau substituenții acestuia.

1.1.TIPURI DE ALIMENTAȚIE ÎN CREȘTEREA VIȚEILOR

Pana la vârsta de trei săptămâni, este recomandat ca vițeii sa primească lapte de la mamele lor. Cantitatea totala de lapte integral, consumata de un vițel in perioada de alăptare, variază intre 200 si 400 de kilograme. De la vârsta de 3-4 săptămâni, se începe substituirea laptelui integral cu laptele smântânit. Treptat, pana la înlocuirea totala. Modul prin care vițeilor le este administrat laptele este denumit sistem de alăptare.

Fermierii au de ales între:

alăptarea naturala

alăptarea artificiala

Alăptarea naturala este un sistem cu aplicabilitate minima, in condițiile modernizării zootehniei. Consta in consumul laptelui direct din uger, fiind cel mai simplu sistem, din punct de vedere tehnic. Se elimina contactul cu aerul din adăpost, prin trecerea laptelui din glanda mamara a vacii, direct in organismul vițelului, excluzând-se totodată contactul cu mana crescătorului sau cu recipientul. Dintre dezavantaje, se remarcă imposibilitatea evaluării cantitative a laptelui consumat, situație ce exclude posibilitatea unei selecții ulterioare, pe baze științifice. Vițelul consuma mai mult lapte decât necesarul unei creșteri raționale, pierzând-se totodată o cantitate de lapte ce ar fi putut valorificata. O alăptare insuficienta poate produce răniri vacii, la nivelul ugerului, datorate comportamentului vițelului stresat fizic si psihic. Prin alăptarea naturala pot fi transmise boli (tuberculoza, bruceloza), de la vaca-mama, iar înțărcarea vițeilor se face greu, aceștia fiind afectați de separare. Sunt dezavantaje care i-au obligat pe majoritatea crescătorilor sa caute alte mijloace de alăptare, prin care sa asigure simultan necesitățile proprii si ale vițelului.

Alăptarea artificiala  presupune administrarea indirecta a laptelui către vitei, cu ajutorul unor recipiente de colectare sau a unor instalații speciale. Sistemul permite înlocuirea laptelui cu înlocuitor de lapte. Prin alăptarea artificiala, cantitatea de lapte consumata de vițel poate fi cunoscuta exact, informație importanta pentru o creștere raționala. In funcție de furajele disponibile, se poate reduce treptat cantitatea de lapte, in baza unor scheme de alăptare, iar vițeii vor fi obligați sa consume timpuriu furaje uscate, in cantități tot mai mari. Prin separarea vițelului de mama sa, imediat după fătare, se elimina toate dezavantajele naturale, iar laptele primit va fi numai de la vaci sănătoase. Alăptarea artificiala este uneori mecanizata, putând fi hrănit un grup mai mare de vitei, cu ajutorul unor instalații care limitează efortul crescătorilor.

1.2.SISTEME AUTOMATE DE HRĂNIRE PENTRU VIȚEI DE LAPTE, PRE-ÎNȚĂRCARE UTILIZATE ÎN ALTE ȚĂRI

Sisteme de hrănire automată a vițeilor, controlate de calculator sunt la mare căutare în Midwest din cauza avantajelor de economisire a forței de muncă. Sisteme de hrănire automată a vițeilor constau dintr-o unitate de sine stătătoare, care încălzește apa, se dispensează o cantitate programată de înlocuitor de lapte și se amestecă înlocuitorul de lapte cu apă într-un recipient din care vițelul poate suge printr-o stație de alimentare cu tetină. O singură unitate de hrănire programabila, cu două stații de alimentare tip biberon va costa aproximativ intre 18.000$ și 22.000$. Un computer ce oferă un program cu mai multe opțiuni și capabilități de alimentare va costa în plus 4.000$.

Amortizarea unui astfel de sistem se face astfel: presupunem că avem un sistem de hrănire automată a vițeilor cu două stații de alimentare cu biberon, care costa in total 22.000$. Un sistem de acest tip ar oferi capacitatea de a hrăni două loturi a cate 25 de viței timp de până la 10 săptămâni. In primele 7 până la 10 zile vițeii vor trebui hrăniți cu sticla cu tetină pentru a se putea învață cu hrănirea automata. S-a observat că vițeii petrec 30 până la 50 de minute pe zi la stația de hranire. Dacă dorim sa scoatem din țarc viței cu vârsta de peste 70 de zile, avem o medie de hrănire de 60 de zile. Un vițel consumă intre 1 și 1.43 l pe zi, acest lucru ar permite șase grupuri a cate 25 de viței pe lot într-un an, cu două seturi pentru un total de 300 de viței pe alimentator per an. Prin urmare, costul sistemului de hrănire automată a vițeilor se calculează astfel: 22.000 $ împărțit la 5 ani cu o amortizare de 4,400 $ pe an, împărțit la 300 de viței pe an = 14.66 $ cost per vițel.

Cu ajutorul unui sistem de hrănire automată a vițeilor se poate obține o creștere a cantității de hrana pe zi per vițel, comparativ cu hrănirea individuală. Acest lucru a fost investigat de cercetătorul danez M.B. Jensen pe parcursul întregii perioade de hrănire doar cu lapte. El a descoperit că a fost mai bine a se reduce numărul de hrăniri pe zi, in locul reducerii cantității totale de hrană pe zi. Această strategie de hrănire a dus la creșterea cantității consumate înainte de înțărcare și mai puțin timp petrecut în stația de hrănire.

Atunci când se utilizează un sistem automat de hrănire, de obicei, vițeii sunt hrăniți cu 0,5 până la 2,0 litri pentru o hrănire având între 4 și 8 mese pe zi. Mai multe studii au indicat în cazul în care vițeilor li s-au oferit mai multe porții mici, au existat un număr mai mare de vizite nerecompensate (viței nu pot primi lapte) la stația de hrănire cu tetină. Mai multe vizite au dus la creșterea timpului petrecut la stațiile de hrănire și s-a observat o creștere a cantității consumate de viței. Această problemă a dus la o aglomerare de către un număr tot mai mare de viței pe fiecare stație de hrănire cu biberon. Vițeii au fost mulțumiți cu 5 până la 6 mese pe zi, reducând astfel numărul de vizite nerecompensate pe zi la jumătate. Prin urmare, Jensen a concluzionat că numărul corespunzător de porții de hrănire zilnice poate depinde de volumul total alimentat per vițel pe zi.

Hrănirea vițeilor într-un țarc permite observarea mai ușoară a stării de sănătate a vițeilor prin monitorizarea aportul de lapte si poate oferi o lista cu alarme pentru viței care nu se încadrează în parametrii stabiliți. În plus, alimentatorul automat poate monitoriza numărul de vizite, numărul de vizite nerecompensate și recompensate, precum și rata consumului de lapte. Svensson și Jensen au concluzionat cel mai sigur indicator al sănătății vițelului este numărul de vizite nerecompensate la stația de alimentare. Acest număr de vizite este mai important decât cantitatea consumată pe zi și/sau rata consumului. Mai multe vizite indica un vițel mai activ.

Sistemul de hrănire automată a vițeilor oferă posibilitatea de a creste viței de lapte pre-înțărcați cu munca manuală mai puțina decât in cazul sistemelor tradiționale de hrănire, oferind în același timp un potențial maxim de creștere. Recuperare a investiției depinde strict de numărul de animale care urmează să fie hrănite pe an, precum și de costurile si disponibilitatea forței de muncă din zona respectivă.

1.3.ARGUMENTE PRO ȘI CONTRA HRĂNIRII AUTOMATE A VIȚEILOR

O parte a comportamentului natural al unui vițel, spun experții, este să consume mai multe mese, cantitativ mai mici, pe tot parcursul zilei. Sistemul de hrănire automată a vițeilor, permite vițeilor sa păstreze un comportament natural, dar va necesita unele schimbări în modul în care fermierii gestionează turma.

"Unul dintre principalele avantaje ale sistemelor de hrănire automate este ca ele permit unui vițel să fie alăptat conform instinctului natural, cu mai multe mese în cantități mici pe durata unei zile", explica Dr. Nancy Charlton pentru DeLaval Canada (unul dintre cei mai mari producători de sisteme de hrănire automată a vițeilor). "Vițelul poate bea ce vrea si când vrea. Noi nu impunem gândirea noastră, dar permitem vițelului posibilitatea de a-și exprima comportamentul natural ".

Pentru hrănirea vițeilor din rasa Grober se poate începe alăptarea automata la trei până la șapte zile de la naștere, iar producătorii pot programa software-ul aparatului pentru a determina cât de mult lapte poate consuma un vițel într-o zi. Vițeii din rasa Holstein pot bea până la 12 litri pe zi, dar cel mai adesea media este de 8 până la 10 de litri pe zi, spune Charlton, iar acestea ar trebui să aibă posibilitatea de a bea mai mult, în sezonul rece atunci când temperaturile devin mai scazute.

Prospețimea hranei este un alt avantaj, spune Jan Ziemerink, un specialist în alimentație ce lucrează cu Grober Nutrition și Förster-Technik America de Nord, cel mai mare producător mondial de sisteme automate de hrănire a vițeilor. "Sistemul prepară și amestecă porțiile când intră vițelul în stația de hrănire cu tetină, astfel încât acestea sunt întotdeauna în stare proaspătă, iar temperatura este menținută în parametri stabiliți", explică el, adăugând că mașinile noi au sistem de calibrare automată care asigură fiecărei porții cantitatea potrivită de apă. "Componentele hrănirii sunt întotdeauna dozate cu precizie și blenderul amestecă înlocuitorului de lapte foarte precis."

"Viteza cu care vițelul bea este importantă deoarece puteți vedea dacă vițeii se vor îmbolnăvi înainte de a apărea semnele bolii. Sistemul de hrănire automată a vițeilor ține evidența vitezei de consum în ultimele câteva zile și oferă o alarmă în cazul în care un animal a băut mai lent ", spune el. "Acest lucru ar putea fi un indicator timpuriu al bolii, astfel încât să puteți verifica vițeii și în loc de a ajunge la medicamente, s-ar putea folosi vitamine sau electroliți."

Sistemul de hrănire automată a vițeilor face procesul de înțărcare mai ușor, spune Charlton, pentru că aportul de lapte al vițeilor se reduce treptat. Acest lucru reduce stresul vițelului, care, la rândul său, reduce incidența de pneumonie și de boli post-înțărcare.

De asemenea, producătorii trebuie să continue să acorde o atenție deosebita elementelor bază, cum ar fi un bun flux de aer, managementul colostrului, dar și asigurarea unui mediu uscat și curat. Este de asemenea important să se mențină contactul cu vițeii pentru a identifica vițeii care ar putea avea nevoie o atenție individuală."Ventilația este numărul unu ca și prioritate. În cazul în care nu există nici o ventilație, puteți pune orice fel de mașină în hambar și veți avea în continuare viței bolnavi", sfătuiește Ziemerink

1.4.DISTRIBUITORUL AUTOMATIZAT PENTRU VIȚEI LELY CALM

Oricine dorește să obțină vaci care să producă lapte de calitate pentru o perioadă  îndelungată trebuie mai întâi să optimizeze creșterea vițeilor. Distribuitorul automatizat pentru viței Lely Calm Compact garantează creșterea și dezvoltarea optimă a acestor animale tinere. Vițeii se pot bucura în continuare de ritmul lor natural și pot bea oricând doresc, în mod controlat, în timp ce munca personalului se reduce la minimum. În fond, vițeii de astăzi sunt vacile de mare performanță de mâine.

Când vițelul se alăptează de la mama lui, el bea de obicei porții adecvate, repartizate de-a lungul zilei. Cu toate acestea, în fermele de vaci de lapte din prezent, rațiile vițeilor sunt limitate la una sau două porții pe zi, în cazul hrănirii manuale. Din aceste motive, Lely a introdus distribuitorul automatizat pentru viței Lely Calm, care furnizează numărul corect de porții de hrană și cu concentrația adecvată, de-a lungul întregii zile, asemenea ritmului natural de hrănire al vițeilor.

Vițelul care intră în stația de hrănire este recunoscut după emițătorul electronic pe care îl poartă și, conform planului de hrănire al vițelului, distribuitorul Lely Calm decide dacă acesta primește hrană și în ce cantitate.

După stabilirea unei rații minime și maxime pentru fiecare vițel, distribuitorul va stabili automat rația vițelului care intră în stația de hrănire. Dacă vițelul chiar are voie să se hrănească, distribuitorul pregătește imediat o porție de lapte la temperatură programată în prealabil.

Distribuitorul automatizat pentru viței Lely Calm le oferă acestora un start excepțional, permițând fermierului o economisire a mâinii de lucru, oferind astfel  importante avantaje economice.

AVANTAJE:

Rată de creștere accelerată

O mai bună dezvoltare a rumenului

Gestionarea individuală a vițeilor

Temperatura constantă și precisă a laptelui

Orar de hrănire flexibil

Înțărcare fără stres

Flexibilitatea muncii

Economie de timp

Adecvat pentru fermele de toate mărimile,

Fiabil, necesită întreținere minimă

DESCRIEREA SISTEMULUI

Cum am prezentat în capitolul anterior există mai multe tipuri de instalații de hrănire a vițeilor de lapte, fiecare sistem având avantaje și dezavantaje pentru fermele din țara noastră.

Avantajele acestor echipamente, deja existente, sunt reprezentate de permiterea ca vițelul să fie alăptat conform instinctului natural, cu mai multe mese în cantități mici pe durata unei zile, posibilitatea hrănirii un grup mare de vitei și reducerea efortul crescătorilor, etc.

Marile dezavantaje sunt reprezentate de prețul mare de achiziție, lipsa de flexibilitate a echipamentelor cu privire la consumabile (lapte praf, medicamente, suplimente nutritive) echipamentele fiind dedicate unui singur furnizor de astfel de consumabile. Un alt dezavantaj este reprezentat de posibilitatea crescută de transmitere a bolilor de la un vițel la altul în cadrul aceluiași țarc, prin lipsa unui sistem complet de spălare și dezinfectare a tetinei după fiecare hrănire.

Având ca bază aceste caracteristici ale echipamentelor existente s-a născut ideea realizării unui echipament original care are ca prioritate piața zootehnică româneasca, care este flexibil în ceea ce privește consumabilele utilizate și nu în ultimul rând care are în vedere prevenția transmiterii bolilor între viței pe baza sistemului de spălare a tetinei. De asemenea s-a ținut cont și de simplificarea meniurilor utilizatorului.

Figură 2-1 Schema de principiu a instalației

Lista componentelor sitemului de hrănire automata a vițeilor:

Debitmetru tanc 1 (FM1)

Debitmetru tanc 2 (FM2)

Electrovalva 1 (EV1)

Electrovalva 2 (EV2)

Electrovalva 3 (EV3)

Electrovalva 4 (EV4)

Electrovalva 5 (EV5)

Electrovalva 6 (EV6)

Electrovalva 7 (EV7)

Electrovalva 8 (EV8)

Electrovalva 9 (EV9)

Electrovalva 10 (EV10)

Electrovalva 11 (EV11)

Electrovalva 12 (EV12)

Pompa dozaj peristaltică 1 (PP1)

Pompa dozaj peristaltică 2 (PP2)

Pompa dozaj peristaltică 3 (PP3)

Pompa alimentare mixer (P1)

Pompa de transfer, alimentare (P2)

Motor alimentare lapte praf

Motor mixer

Rezistenta de încălzire apa pentru prepararea laptelui (R1)

2.1.ALGORITMUL DE FUNCȚIONARE

Algoritmul de funcționare este următorul:

1.Identificare vițel

1.1.Dacă vițelul nu a fost hrănit in acea perioada de zi, deschide trapa de acces

1.2.Dacă vițelul a fost hrănit se verifică cantitatea consumată

1.3.Dacă este sub cantitatea maximă stabilită se deschide trapa de acces

2.Prepara laptele in mixer

2.1.Face o estimare a cantității de apa necesara pentru mixare la temperatura optimă (ex. 67 grade) și în funcție de aceasta, pornește pompa de alimentare P1 si deschide valvele EV1, EV2 si EV3

2.2.Calculează cantitatea de lapte praf

2.3.Pornește mixerul

2.4.Injectează aditivii prin intermediul pompelor dozatoare

2.5.După omogenizare, completează cu apa rece si calda pana la cantitatea necesara

2.6.Continua mixarea pana la expirarea timpului stabilit

3.Transfera laptele preparat din mixer in bol

3.1.Pornește pompa de transfer P2 si deschide valva EV4 sau EV8

3.2.Contorizează cantitatea de lapte prin intermediul flowmeter-ului FM1 sau FM2

3.3.După ce s-a contorizat cantitatea de lapte, se urmărește daca flowmeter-ul mai contorizează.

3.3.1.Daca da, alarma (recalibrare).

3.3.2.Daca nu, închide valva EV4 sau EV8 si oprește pompa de transfer

4.Hrănirea vițelului

4.1.Deschide valva EV5 sau EV9

4.2.Contorizează cantitatea de lapte pe care o mănâncă vițelul

4.3.Când s-a terminat, închide valva EV5 sau EV9 si închide trapa de acces vițel

5.Ciclul de spălare

5.1.Prima spălare se face cu apa fierbinte

5.2.Pornește pompa de alimentare si deschide valva EV1 si EV3 (se închide după timpul prestabilit)

5.3.Pornește mixerul (se oprește după timpul prestabilit)

5.4.Pornește pompa de transfer, se deschide electrovalva EV4 sau EV8

5.5.Se contorizează apa care intra in bol si in același timp se face si o recalibrare (cantitatea de apa care intra in mixer trebuie sa fie aceeași cu cea contorizata de flowmeter)

5.6.Se oprește pompa de transfer, se închide EV4 sau EV8, se deschide valva de golire EV6 sau EV10, urmărind-se debitul de apa

5.7.Pornește pompa de alimentare si deschide valva EV1 si EV7/EV11 (se închide după timpul prestabilit)

5.8.Se deschide valva de golire EV6 sau EV10, urmărind-se debitul de apa

5.9.A doua spălare se face cu apa rece (vezi 5.1)

2.2.ELEMENTE COMPONENTE ALE SISTEMULUI

Debitmetrul folosit este:

Figură 2-5 Debitmetru GICAR 9.0.96.02C

Denumire Contor volumetric – debitmetru GICAR 9.0.96.02C – 400004

Descriere: dimensiune 1/4"

Material oțel inoxidabil

Versiunea cu LED

Conector mufa trei pini

Producator Gicar

Pentru calibrarea cantităților de apă în funcție de temperatură a se vedea Anexa 1

Figură 2-6 Localizarea debitmetrului de sub tancul de lapte nr.1

Pompa de apa si cea de transfer:

Pompe periferice industriale OSIP PB 50

Descriere:pompă periferică din alamă, concepută pentru a dezvolta o presiune ridicată ce are consum redus de energie. Această pompă este realizată în întregime din alamă, pentru a evita orice problemă de blocare. Acestă pompă este destinată în special pentru aplicații sanitare și industriale.

Caracteristici constructive:

Rotor: alamă 58

Corpul pompei: alamă 58

Arbore motor: oțel inoxidabil AISI 420

Carcasa motorului: tip aluminiu – MEC 63

Motor: închis, ventilat extern

Vopsea: Electroforetic negru

Suruburi: oțel S.

Clasa de izolație: F

Clasa de protecție: IPX5

Qmax = 35 l/min

Hmax = 36 m

P = 0.58 kW (0.7HP)

I=2.8 A

RPM = 2800

230V AC / 50 Hz / C=12µF

Figură 2-8 Localizarea celor două pompe (de apă și cea de transfer)

Motoreductor melcat

Motoreductoare melcate cu factor de reductie intre i=5 si si i=100.

Motoredutoarele melcate pot avea mai multe pozitii de montaj, existente in 10 marimi, de la 0,06kW pana la 9,2kW. Orice motoreductor are o rezistenta mecanica foarte buna si o greutate redusa, cu carcasa proiectata pentru mai multe tipuri de prindere si montaj. Carcasa motoreductoarelor este realizata din aluminiu pentru gabaritele 025-105. Motoreductoarele din aluminiu sunt lubrifiate pe viata.

Prinderea dintre motor si reductor se poate face direct numai daca motorul are flansa B5.

Caracteristici ale structurii:

Carcasa turnată din aliaj de aluminiu dispune de o gama larga de opțiuni de montare

Nervurile de la suprafață garantează o rigiditate bună și o mai bună disipare a căldurii

Arborele melcat răcit asigură eficiență ridicată și cuplu mărit

Nivel scăzut de zgomot și funcționare constantă, corespunzătoare pentru funcționarea de lungă durată

Ușor și cu rezistență mecanică ridicată

Materiale principale:

Carcasă din turnat din aliaj de aluminiu

Arborele melcat din oțel tratat termic

Roată dințată elicoidală din aliaj nichel-bronz

Vopsea: Carcasă turnată din aliaj de aluminiu: tratament de suprafață de curațare cu nisip și antiseptice blu RAL 5010

Reductor ELECTRO ADDA tip 0100312 KMV 40

Motor ELECTRO ADDA tip 1001-103 1054, FC 63 B5:

IP55 230VAC, P=0.18Kw, I=1.49 A, RPM=1390, C=12µF

Figură 2-9 Motor cu reductor pentru axul melcat

Figură 2-10 Șnec pentru transportul laptelui praf direct în mixer

Dozarea cantităților s-a făcut prin cuante de timp. Regulatorul presiunii apei este setat la 4 bari. Cum se știe, volumul apei se modifică în funcție de temperatură. Pentru calcularea cantității de lapte se pot stabili dozele folosite în funcție de rețeta optimă pentru vârsta vițelului raportat la consistența laptelui praf, raportat la cantitatea de apă încălzită la 630 C și la cantitatea de apă rece adăugată până la completarea rețetei cerute, în relație directă cu rotațiile motorului ce angrenează axul transportor melcat prin intermediul cutiei de transfer.

Figură 2-11 Schema de principiu pentru transportul laptelui praf direct în mixer

Viteza de deplasare a produsului de-a lungul șnecului:

v0 = (n/60)*S [m/s]

n-turația șnecului [rot/min]

p-pasul dintre doua spire ale șnecului [m]

S-reprezintă densitatea laptelui praf [kg/m3]

Pentru determinarea capacității de lucru a șnecului s-a folosit relația:

[t/h]

Figură 2-12 Cotele șnecului

în care: D – diametrul exterior al șnecului [m]

d – diametrul ax [m]

γ – greutatea volumetrica a materialului transportat [t/m3]

C – coeficient de umplere (C = 0,3 pentru lapte praf)

α – coeficient de corecție în funcție de înclinare (k = 1 pentru 00 înclinare)

Cuvă de inox alimentar AISI 304, pentru lapte praf:

Figură 2-13 Recipietul pentru lapte praf și/sau aditivi

Pompele de dozare

Pentru vitamine, antibiotice si suplimente nutritive

Model tip SEKO PPR0018A1000

Presiune 0,1 bar

Debit 18 l/h

Presiune 0.1 bar

Debit maxim 1,5 l/h

230 VAC, 50Hz, P=10W, I=0.4 A

Figură 2-14 Pompe de dozare (vitamine, antibiotice)

Mixerul unde este amestecat laptele praf cu apa încălzită și eventualele adiții de la pompele de dozaj

Motorul folosit este ELECTRO ADDA tip 1001-103 1054, FC 63 B5:

IP55 230VAC, P=0.18Kw, I=1.49 A, RPM=1390, C=12µF

Relee pentru acționarea pompelor de dozare DP1, DP2 si DP3

Releele utilizate sunt: MY4N modelul cu indicator de funcționare încorporat, avand urmatoarele caracteristici:

Figură 2-16 Relee MY4N

Sarcina nominală 3 A

Curent nominal de transmisie 3 A

Tensiune maximă de contact 250 VAC, 125 Vcc

Curent maxim de contact 3 A

Configurația de contact 4PDT

Structura de contact Unic

Materiale de contact Au placări + aliaj de ag

Temperatură de funcționare ambientală -55 până la 70 ° C

Umiditate ambientală de funcționare 5% până la 85%

Rezistență la contact 50 mΩ max.

Timp de funcționare 20 ms max.

Timp de eliberare 20 ms max.

Frecvența maximă de operare

Mecanică 18.000 operațiuni / h

Sarcina nominală 1.800 operațiuni / h

Rezistența la izolație 100 MΩ min.

Rezistență dielectrică:

Între bobină și contacte

Între contacte de 2.000 VAC la 50/60 Hz timp de 1 min.

Polaritate diferită

Între contactele din

Aceeași polaritate la 1000 VAC la 50/60 Hz timp de 1 min.

Rezistența la vibrații

Distrugerea 10 la 55 până la 10 Hz, o singură amplitudine de 0,5 mm (amplitudine dublă de 1,0 mm)

Defecțiune 10 la 55 până la 10 Hz, amplitudine unică de 0,5 mm (amplitudine dublă de 1,0 mm)

Rezistența la șocuri:

Distrugere 1.000 m / s2

Defecțiune 200 m / s2

anduranță:

Mecanic

AC: 50.000.000 operațiuni min.

DC: 100.000.000 operațiuni min.

(Frecvență de comutare: 18.000 operațiuni / h)

Electrice * 4 200.000 operațiuni min.

(Sarcină nominală, frecvență de comutare: 1 800 operații / h)

Relee de acționare a pompelor de apă, transfer, spălare, mixer și acces tetină

Releele utilizate sunt: MK3P-I modelul cu indicator de funcționare încorporat, având următoarele caracteristici:

Figură 2-17 Relee MK3PN

Indicator LED și diodă

Rezistență la contact 50 m max.

Durata de funcționare AC: 20 ms max. DC: 30 ms max.

Timp de eliberare 20 ms max.

Frecvență de operare Mecanică 18.000 de operațiuni / oră

Electrice 1800 de operațiuni / oră (sub sarcină nominală)

Rezistența la izolație 100 M min. (La 500 VDC)

Puterea dielectrică 2500 VAC, 50/60 Hz timp de 1 minut între bobină și contacte

1000 VAC, 50/60 Hz timp de 1 minut între contactele acelorași poli, între

Terminale de aceeași polaritate

2,500 VAC, 50/60 Hz timp de 1 minut între piese care transportă curenți, fără sarcină

Părți și terminale de polaritate opusă

Vibrații Durabilitatea mecanică 10 la 55 Hz, amplitudinea dublă de 1,50 mm (0,06 in)

Durată de funcționare a defecțiunii 10 la 55 Hz, amplitudine dublă de 1,00 mm (0,04 in)

Durabilitatea mecanică 1.000 m / s2 (aproximativ 100 G)

Durată de funcționare a defecțiunii 100 m / s2 (aproximativ 10 G)

Temperatura mediului înconjurător Funcționare: -10 până la 40 ° C (14 până la 104 ° F)

Umiditate 35-85% RH

Durată de viață a mașinii 10 milioane operațiuni min. (La o frecvență de operare de 18.000 de operațiuni / oră)

100.000 de operații electrice la sarcina nominală (la o frecvență de operare de 1.800 de operațiuni / oră)

Greutate Aprox. 0,85 g (3,0 oz)

2.3.MICROCONTROLERUL DSPIC30F4011

Familia de controlere de semnal digital dsPIC30F include controlere cu o gama de pini variata(40 și 44, 64 si 80), memorie program de diferite mărimi (12KB, 24KB, 48KB si 144KB) și dimensiuni variate a memoriei RAM (512B, 1024B si 2048B). Aceste lucruri fac ca familia de controlere să fie potrivită pentru o gamă largă de aplicații de înaltă performanță în domeniul controlului și prelucrarea de semnale digitale. Controlerul are pinii compatibili cu familia de controlere dsPIC30F, aceasta permițând o migrație ușoară între aceste familii de controlere în funcție de necesitățile de funcționare specifice, resursele de calcul și prețul de cost impuse de aplicație.

Familia de controlere dsPIC30F4011/4012 folosește o arhitectura pe 16 biți puternică, integrând caracteristicile de control ale unui microcontroler (MCU) cu capabilitățile de calcul ale unui procesor de semnal digital (DSP), fiind ideal pentru integrarea in aplicații ce necesita viteză mare, calcul repetitiv și siguranță a controlului.

Motorul DSP cu acumulator dublu de 40 de biți, suport hardware pentru operații de împărțire, multiplicator 17-biti x 17-biti, număr mare de registre de lucru pe 16 biți și o gamă variată de moduri de adresare a datelor, fac ca unitatea centrala de procesare (CPU) să aibă capacități extensive de procesare matematică. Sistemul de tratare a întreruperilor flexibil și deterministe cuplat cu un sistem puternic de periferice, permit controlerelor dsPIC30F4011/4012 să fie potrivite pentru aplicații de control. Accesul direct la memorie (DMA) permite transferul datelor între memoria DMA RAM dedicată și diverse periferice. Siguranța în funcționare, memoria program de tip Flash, asigură călibilitatea aplicațiilor care utilizează aceste controlere.

Codul sursă este prezentat in Anexa 2.

Caracteristicile principale ale microcontrolerului

Unitate centrală de procesare de înaltă performanta:

arhitectura Harvard modificata

set de instrucțiuni a compilatorului C optimizat

lățimea datelor de 16 biți

lățimea instrucțiunilor pe 24 biți

adresarea liniara a memoriei de date pana la 48KB

adresarea liniara a memoriei program pana la 16KB cuvinte instrucțiune

16 registre generale pe 16 biți

Caracteristici motor DSP

doi acumulatori pe 40 de biți cu opțiuni de rotunjire si saturare

moduri de adresare flexibil si puternic

operații de multiplicare 17×17 fracționare/întregi

multiplicări si acumulări intra-un singur ciclu

deplasări ±16 biți singur ciclu

Controler de întreruperi:

pana la 30 surse de întrerupere disponibile

pana la 3 întreruperi externe

4 excepții procesor

Periferice:

Pini curent intrare / ieșire 25mA/25mA

5 module temporizare pe 16 biți

Funcție captura intrare 16 biți

Funcție comparare/ieșire PWM 16 biți

I2C Module

2 module UART cu buffer FIFO

1 modul CAN (compatibil 2.0)

Module de temere/captura/comparatoare/PWM:

6 canale ieșire PWM

3 generatoare de cicluri

Polaritate de ieșire programabilă

Controlul timer-ului pentru modul complementar

Control manual al ieșirii

Trigger pentru conversii analog-digital A/D

Caracteristicile modulului interfetei de codare:

Intrare faza A, faza B și index puls

Contor de poziție sus/jos pe 16 biți

Status contorizare direcție

Mod de poziționare a măsurării (x2 și x4)

Filtre de zgomot digital programabile pe intrări

Mod alternativ pe 16 biți Timer/Counter

Caracteristici analogice:

Convertor analog-digital (A/D) pe 10 biți cu 4 intrări S/H:

rata de conversie de 500 Kps

9 canale de intrare

Conversie disponibilă în timpul perioadei de repaus și inactive

Programarea detecției Brown-out și generare Reset

Caracteristici speciale ale microcontrolerului:

Memorie program intensificată Flash:

10.000 cicluri de ștergere/scriere (min.) pentru intervalul temperaturilor industrial (tipic 100 K)

Memorie EEPROM de date:

100.000 cicluri de ștergere/scriere (min.) pentru intervalul temperaturilor industrial (tipic 100 K)

Auto-reprogramabil sub controlul software-ului

Power-on Reset (POR), Timer de pornire (PWRT) și Timer de pornire a oscilatorului (OST)

Cronometru flexibil de supraveghere (WDT) cu un nivel redus de putere a oscilatorului RC, pentru o funcționare fiabilă

Funcție de siguranță Fail-Safe de monitorizare a funcționării ceasului ce detectează defectarea și comută la circuitul oscilatorului RC cu putere redusă

Protecție programabilă a codurilor

Programare în serie pe circuit (ICSP ™)

Moduri de gestionare a energiei selectabile: Sleep, Idle și Alternate Clock

Tehnologia CMOS:

• Tehnologie Flash de mare viteză și consum mic

• Domeniu larg de tensiune de operare (de la 2.5V la 5.5V)

• Domenii industriale și temperaturi extinse

• Consum redus de putere

Figură 2-18 Pinii microcontrolerului utilizat

Tabel 2.1 Descrierea pinilor microcontrolerului dsPIC30F4011

Tabel 2.2 Descrierea pinilor microcontrolerului dsPIC30F4011 – continuare

Unitatea centrala de prelucrare

Unitatea centrala de prelucrare (CPU) a controlerelor dsPIC30F4011 are o arhitectura Harvard modificata pe 16 biti cu un set de instructiuni ridicat, inclusiv un suport semnificativ pentru DSP. Unitatea centrala are cuvantul instructiune de 24 biti cu lungimea variabila a cuvantului masina. Contorul program (PC) este de 23 biti si adreseaza pana la 4M x 24 biti din spatiul de memorie program. Este folosit un mecanism de extragere a instructiunii intr-un singur ciclu pentru a asigura o executie predictibila. Toate instructiunile se executa intr-un singur ciclu, cu exceptia instructiunilor care schimba fluxul programului, instructiunea de mutare a unui dublu cuvant (MOV.D) si instructiunile care opereaza cu tabele. Suporta constructia de bucle utilizand instructiunile DO si REPEAT fara a incarca unitatea centrala, ambele instructiuni putand fi intrerupte in orice punct.

Controlerul dsPIC30F4011 are 16 registre de lucru pe 16 biti. Fiecare din aceste registre poate fi folosit ca registru de date, adresa sau deplasament de adresa. Al 16-lea registru de lucru (W15) functioneaza ca pointer de stiva software (SP) pentru intreruperi si apeluri de procedura.

Setul de instructiuni se imparte in doua clase de instructiuni: microcontroler (MCU) si procesor de semnal digital (DSP). Aceste doua clase de instructiuni sunt integrate intr-o singura unitate centrala de procesare. Setul de instructiuni include multe moduri de adresare si este proiectat pentru o eficienta optima a compilatorului C. Pentru cele mai multe instructiuni, controlerul dsPIC30F4011 este capabil sa execute o citire din memoria de date, o citire a registrului de lucru, o scriere a memoriei de date si o citire a memorie program intr-un ciclu instructiune. Ca rezultat, poate suporta trei instructiuni ca parametru, permitand operatiei A+B=C sa se execute intr-un singur ciclu.

Adresarea datelor

Spatiul memoriei de date poate fi adresat ca 32K cuvinte sau 64 KB si este impartit in doua blocuri, referite ca memoria de date X si Y. Fiecare bloc de memorie are propria unitate de generare a adresei (AGU – Address Generation Unit). Clasa de instructiuni MCU opereaza doar prin intermediul unitatii de generare a adresei a memoriei X, care acceseaza intreaga harta a memoriei ca un spatiu liniar de date. Clasa de instructiuni DSP opereaza prin intermediul unitatii de generare a adresei atat a memoriei X cat si Y, suportand citirea dubla a operanzilor care imparte spatiul adreselor de date in doua parti.

Buffere circule fara incarcarea unitatii centrale (mod de adresare modulo) sunt suportate de ambele spatii de adrese X si Y. In plus, adresarea circulara a spatiului de adrese X poate fi utilizata de oricare clasa de instructiuni MCU. Unitatea de generare a adresei X suporta adresarea inversata, simplificand astfel reordonarea datelor de intrare si iesire pentru algoritmii FFT (Fast Fourier Transform).

Partea superioara de 32KB a spatiului de memorie de date poate fi optional mapat in spatiul de memorie program la granita oricarui bloc de 16KB definit de registrul de pagina pe 8 biti (PSVPAG – Program Space Visibility Page). Maparea spatiului de date in cea program face ca orice instructiune care acceseaza spatiul de memorie program sa se comporte ca un spatiu de date. Spatiul de date include 2KB de DMA RAM care in principal este utilizat de transferurile de date DMA dar poate fi utilizat si ca memorie generala.

Motorul DSP

Caracteristicile motorului DSP sunt viteza ridicata, multiplicator 17×17, unitate aritmetico-logica de 40 biti, doi acumulatori de 40 biti si registru de deplasare pe 40 biti. Registrul de deplasare este capabil sa deplaseze valori de 40 biti, pana la 16 biti la stanga sau la dreapta, intr-un singur ciclu. Instructiunile DSP opereaza fara probleme cu toate celelalte instructiuni si sunt proiectate pentru performate in timp real optime. Instructiunea MAC si alte instructiuni asociate, poate extrage concurent doi operanzi de date din memorie cat timp se multiplica si acumuleaza doua registre de lucru in acelasi ciclu. Functionalitatea acestei instructiuni necesita impartirea spatiului de memorie de date si folosirea liniara pentru toate celelalte. Partitionarea spatiului de date este obtinuta intr-un mod transparent si flexibil prin intermediul registrelor de lucru dedicate pentru fiecare spatiu de adrese.

Organizarea memoriei

Arhitectura dsPIC30F4011 are spatiul de memorie de date separat de spatiul program precum si a magistralelor. Aceasta arhitectura permite accesul direct din memoria program al spatiului de date pe durata executiei codului.

Spatiul de adrese program

Spatiul de adrese al memoriei program este de 4M instructiuni. Spatiul este adresabil de valori de 24 biti derivat din contorul program de 23 biti pe durata executiei programului sau pe durata remaparii spatiului de date.

Accesul la spatiul de memorie program este restrictionat la jumatatea inferioara a intervalului de adrese. (0x000000 pana la 0x7FFFFF). Exceptie este utilizarea operatiilor TBLRD/TBLWT care utilizeaza TBLPAG<7> pentru a permite accesul la bitii de configurare din spatiul de memorie de configurare.

Figură 2-19 Memoria program pentru controlerele dsPIC30F4011

Organizarea memorie program

Spatiul memoriei program este organizat in blocuri adresabile pe cuvant. Desi este tratat ca o latime de 24 biti, e vazut ca un cuvant superior si unul inferior, cu octetul superior din cuvantul superior neimplementat. Cuvantul inferior este intotdeauna la adresa para, iar cuvantul superior la adresa impara.

Adresele memoriei program sunt intotdeauna aliniate la cuvantul inferior si adresele sunt incrementate sau decrementate cu doi pe durata executiei codului. Acest aranjament asigura compatibilitatea adresarii spatiului de memorie de date si face posibila accesarea datelor in spatiul de memorie program.

Figură 2-20 Organizarea memoriei program

Vectori de intrerupere

Toate controlerele dsPIC30F4011 au rezervate adresele cuprinse intre 0x000000 si 0x000200 pentru executia vectorilor de intrerupere. Vectorul hardware Reset asigura redirectarea executiei codului de la valoarea implicita a contorului program la codul actual de start. Instructiunea GOTO este programata de utilizator la 0x000000 cu adresa actuala pentru codul de start la 0x000002.

Controlerul are doua tabele de vectori de intrerupere situate de la 0x000004 la 0x0000FF si 0x0001FF Aceste tabele de vectori permite fiecarei din multele surse de intrerupere sa fie tratate separat de rutina de tratare a intreruperii.

Spatiul adreselor de date

Controlerul dsPIC30F4011 are spatiul de memorie de date separat, de latime 16 biti. Spatiul de date este accesat folosind unitati de generare a adresei (AGU) separat pentru operatiile de citire si cele de scriere. Harta memoriei de date a controlerului cu 30KB este prezentata in figura urmatoare.

Figură 2-21 Harta memoriei de date pentru controlerele dsPIC30F4011

Toate adresele efective (EA – Effective Address) din spatiul memoriei de date au o latime de 16 biti si adreseaza un octet in spatiul de date. Acest aranjament ofera intervalului de adrese al spatiului de date, o dimensiune de 64KB sau 32K cuvinte. Jumatatea inferioara a spatiului de memorie de date (EA<15> = 0) este utilizata pentru implementarea adreselor de memorie, in timp ce jumatatea superioara (EA<15> = 1) este rezervata pentru zona vizibila a spatiului program.

Organizarea si alinierea memoriei de date

Pentru a mentine compatibilitatea cu controlerele de generatie anterioara si utilizarea eficienta a spatiului de memorie de date, setul de instructiuni ale dsPIC30F4011 suporta ambele moduri de operare, pe octet si pe cuvant. Accesarea pe octet are drept consecinta faptul ca la calcularea tuturor adreselor efective sunt scalate intern cu un pas prin intermediul alinierii pe cuvant. De exemplu, procesorul recunoaste modul de adresare indirecta modificata ulterior [Ws++], ceea ce va rezulta in valoarea din Ws+1 pentru operarea pe byte si Ws+2 pentru operatiile pe cuvant.

Citirea prin accesarea pe octet va avea ca efect citirea unui cuvant complet care contine octetul respectiv, utilizand cel mai putin semnificativ bit a oricarei adresa efectiva pentru a determina care octet se selecteaza. Memoria de date si registrele sunt organizate ca doua entitati paralele de latime un octet, cu decodarea comuna a adresei dar prin scrierea separata a liniilor. Scrierea prin accesarea pe octet va scrie pe partea corespunzatoare a tabloului sau registrului care se potriveste adresei octetului.

Toate cuvintele accesate trebuie sa fie aliniate la adresa para. Extragerea cuvintelor de date nealiniate nu este suportata, deci trebuie avut grija la mixarea operatiilor pe octet si pe cuvant sau cand se adapteaza codul de la controlerele pe 8 biti. Daca apare o citire sau scriere nealiniata, va fi generata o eroare de adresa.

Toti octetii care se incarca in oricare registru de lucru este incarcat in octetul cel mai putin semnificativ. Cel mai semnificativ octet ramane nemodificat.

Instructiunea de extindere a semnului (SE – Sign Extend) este furnizata pentru a permite utilizatorilor sa schimbe datele pe 8 biti cu semn in valori pe 16 biti cu semn. Alternativ, pentru datele pe 16 biti fara semn, utilizatorii pot sterge cel mai semnificativ bit din oricare registru de lucru prin executia instructiunii zero-extend (ZE) pe adresa apropiata.

Spatiul registrelor de functii speciale

Primii 2K octeti din spatiul apropiat de date (Near Data Space), de la 0x0000 pana la 0x07FF este ocupat de registrele functiilor speciale (SFR – Special Function Registers). Acestea sunt utilizate de procesor si modulele periferice pentru controlul operatiilor din controler.

Registrele speciale sunt distrbuite pe modulele pe care le controleaza si sunt in general grupate impreuna de modul. Multe din spatiul registrelor speciale contine adrese neutilizate, acestea fiind citite ca ‘0’.

Spatiul de date apropiat

Zona de 8KB cuprinsa intre 0x0000 si 0x1FFF este referita ca spatiu de date apropiat (Near Data Space). Locatiile de memorie a acestui spatiu sunt adresabile direct prin intermediul adresei absolute pe 13 biti in interiorul tuturor instructiunilor de acces direct la memorie. In plus, intreg spatiu de memorie este adresabil utilizand instructiunile MOV, care suporta modul de adresare directa a memoriei cu campul de adresa de 16 biti sau prin utilizarea modului de adresare indirecta folosind registrele de lucru ca pointer de adresa.

Accesarea datelor din memoria program utilizand instructiunile tabel

Instructiunile TBLRDL si TBLWTL ofera o metoda directa de citire sau scriere al cuvantului inferior al oricarei adresa din interiorul spatiului program, fara a interveni in spatiul de date. Instructiunile TBLRDH si TBLWTH este metoda de a citi sau scrie cei 8 biti superiori din spatiul program.

Contorul program este incrementat cu doi pentru fiecare cuvant program succesiv de 24 biti. Aceasta permite adreselor de memorie program de a se mapa direct in adresele spatiului de date. Memoria program poate fi astfel privita ca doua cuvinte de 16 biti, fiecare cu acelasi interval de adrese. TBLRDL si TBLWTL acceseaza spatiul care contine cel mai putin semnificativ cuvant de date si TBLRDH si TBLWTH acceseaza spatiul care contine octetul de date superior.

Figură 2-22 Accesarea memoriei program cu instructiuni tabel

Memoria program

Controlerele dsPIC30F4011 contin memorie program interna de tip flash pentru stocarea si executiua codului aplicatiei. Memoria poate fi cititita, scrisa si stearsa pe durata normala de operare.

Memoria program poate fi programata pe doua căi:

programarea prin ICSP (In-Circuit Serial Programming)

programarea pe durata executiei (RTSP – Run-Time Self-Programming)

Programarea prin ICSP permite controlerului dsPIC30F4011 sa fie programat serial in aplicatiile finale. Acest lucru este simplu de realizat cu doua linii, una de ceas si una de date si alte trei linii: alimentarea (VDD), masa (VSS) si Master Clear (MCLR). Aceasta permite producatorilor sa construiasca placi fara a programa controlerele, acestea fiind programate chiar inainte de a fi livrate cu ultima versiune a softului de operare.

Programarea pe durata executiei programului este realizata utilizand instructiunile TBLRD (table read) si TBLWT (table write). Prin acest tip de programare se poate scrie date in memoria program in blocuri sau randuri de 64 instructiuni (192 octeti) sau poate fi scris un singur cuvant de memorie program si stergerea memoriei program in blocuri sau pagini de 512 instructiuni (1536 octeti).

Instructiunile tabel si programarea memoriei Flash

Indiferent de metoda utilizata, programarea memorie Flash este facuta cu instructiunile tabel de citire si scriere. Aceste instructiuni permite accesul direct la spatiul memoriei program pentru a fi citita sau scrisa cat timp controlerul este in modul de operare normala. Adresa tinta de 24 biti in memoria program este formata utilizand bitii <7:0> din registrul de pagina TBLPAG si adresa efectiva din registrul de lucru W specificata in instructiunea tabel, asa cum arata figura.

Figură 2-23 Adresarea pentru registrele table

Modulul Reset

Modulul reset combina toate sursele de reset si controleaza controlerul prin intermediul semnalului SYSRST (Master Reset Signal). Sursele de reset sunt:

POR: Power-on Reset

BOR: Brown-out Reset

MCLR: Master Clear Pin Reset

SWR: Instructiunea RESET

WDT: Watchdog Timer Reset

TRAPR: Trap Conflict Reset

IOPUWR: Illegal opcode and Uninitialized W

Figură 2-24 Diagrama bloc a sistemului Reset

Orice sursa activa Reset va provoca activarea semnalului SYSRST. Multe registre asociate cu unitatea centrala de procesare si periferice sunt fortate in starea Reset. Cele mai multe registre nu sunt afectate de reset; starea acestora este necunoscuta la resetul prin alimentare (POR) si neschimbata de toate celelalte surse de reset.

Toate tipurile de Reset ale controlerului vor fi setate de bitul de stare corespunzator din registrul RCON. Resetul la alimentare (POR) va sterge toti bitii, cu exceptia bitului POR (RCON<0>). Utilizatorul poate seta sau sterge orice bit pe durata executiei codului. Bitii din RCON servesc doar ca biti de stare. Prin setarea unui bit de stare Reset in software nu va cauza aparitia unui reset in controler.

Controlerul de intreruperi

Controlerul de intreruperi ale dsPIC30F4011 reduce numeroasele semnale periferice de cerere de intrerupere la un singur semnal de cerere de intrerupere catre unitatea centrala de prelucrare.

Controlerul de intreruperi are urmatoarele caracteristici:

pana la 8 exceptii procesor si trape software

7 nivele de prioritate selectabile

tabel cu vectori de intrerupere (IVT – Interrupt Vector Table) cu pana la 118 vectori

vector unic pentru fiecare intrerupere sau sursa de exceptie

prioritate fixa in interiorul nivelului de prioritate specificata de utilizator

tabel cu vectori de intrerupere alternativ pentru depanare

timp de asteptare fix la intrarea si returnarea intreruperii

Tabelul vectorilor de intrerupere

Tabelul vectorilor de intrerupere este localizat in memoria program, pornind de la locatia 000004h. Tabelul vectorilor de intrerupere contine 126 de vectori compus din 8 vectori nemascabili si pana la 118 surse de intrerupere. In general, fiecare sursa de intrerupere are propriul vector. Fiecare vector de intrerupere contine o adresa de 24 biti. Valoarea programata in locatia fiecarui vector de intrerupere reprezinta adresa de start din rutina de tratare a intreruperii (ISR – Interrupt Service Routine).

Vectorii de intrerupere au prioritati in functie de prioritatea lor naturala; aceasta prioritate este legata de pozitia acestora in tabelul vectorilor. De exemplu, intreruperea asociata cu vectorul 0 va avea prioritate peste toti vectorii de intrerupere.

Controlerul dsPIC30F4011 are implentat pana la 67 intreruperi unice si 5 trape nemascabile.

Tabelul vectorilor de intrerupere alternativi

Tabelul vectorilor de intreruperi alternativ (AIVT – Alternate Interrupt Vector Table (AIVT) este localizat dupa tabelul vectorilor de intrerupere. Accesul la aceasta tabela este asigurat de bitul de control ALTIVT (INTCON2<15>). Daca bitul ALTIVT este setat, toate procesele de intrerupere si exceptii utilizeaza vectorii alternativi in schimbul vectorilor impliciti. Vectorii alternativi sunt organizati in acelasi mod ca vectorii impliciti.

Tabelul vectorilor de intrerupere alternativ suporta depanarea aceasta inseamna ca se poate comuta intre aplicatie si mediul de depanare fara a fi necesara reprogramarea vectorilor de intrerupere. Aceasta caracteristica face posibila comutarea intre aplicatii pentru evaluarea diferitilor algoritmi in timpul rularii. Daca vectorii alternativi nu sunt necesari, atunci trebuie programati cu aceleasi adrese utilizate de tabela vectorilor de intrerupere.

Tabel 2.3 Tabelul vectorilor de intrerupere

Accesul direct la memorie

Accesul direct la memorie (DMA) este un mecanism foarte eficient de copiere a datelor registrele speciale (ex. registrul de receptie a UART) si buffere sau variabile din memoria RAM cu interventia minima a unitatii centrale. Controlerul DMA poate copia automat intreg blocul de date fara a fi necesara citirea sau scrierea registrelor de functii speciale de fiecare data cand apare o intrerupere. Controlerul DMA foloseste o magistrala dedicata pentru transferurile de date si de aceea nu sunt furate cicluri din fluxul de executie al codului. Pentru a exploata capabilitatile DMA, bufferele sau variabilele trebuie localizate in memoria RAM DMA.

Perifericele controlerului dsPIC30F4011 care pot folosi accesul direct la memorie sunt prezentate in tabelul urmator, cu numarul cererii de intrerupere asociat.

Tabel 2.4 Acces DMA cu numarul cererii de intrerupere asociat

Controlerul DMA are opt canale identice de transfer a datelor. Fiecare canal are propriile registre de control si stare si poate fi configurat sa copieze date din buffer localizat in DMA RAM in registrele cu functii speciale sau din registrele speciale in bufferul DMA RAM.

Controlerul DMA suporta urmatoarele caracteristici:

transferuri de date pe octet sau cuvant

transferuri de la periferice in DMA RAM sau din DMA RAM spre periferice

adresarea indirecta a locatiilor DMA RAM cu sau fara incrementarea ulterioara automata

adresarea indirecta a perifericilor

transferuri in bloc

transferuri continue de blocuri – reincarcare adresa de start a bufferului DMA RAM dupa fiecare transfer complet al blocului

initializarea manuala sau automata a transferurilor de blocuri

fiecare canal poate selecta din 20 surse posibile a surselor sau destinatiilor datelor

Pentru fiecare canal DMA este generata o cerere de intrerupere DMA cand transferul unui bloc este complet. Alternativ, o intrerupere poate fi generata cand jumatate de bloc a fost transferat.

Figură 2-25 Arhitectura DMA

Configurarea oscilatorului

Sistemul oscilator al controlerului dsPIC30F4011 are urmatoarele proprietati:

oscilatoare variate externe sau interne, cum sunt sursele de ceas

oscilator intern

comutarea ceasurilor intre surse de ceas variate

ceas cu postscaler programabil

monitor pentru detectarea defectarii ceasului

Figură 2-26 Diagrama sistemului oscilator al controlerului dsPIC30F4011

Porturi de intrare/iesire

Toti pinii controlerului (cu exceptie VDD, VSS, MCLR si OSC1/CLKIN) sunt partajati intre periferice si porturile paralele de intrare/iesire. Toate intrarile porturilor sunt intrari Trigger Schmitt pentru cresterea imunitatii la zgomot.

Porturi paralele de intrare/iesire

Porturile paralele de intrare/iesire (PIO) au partajate pinii cu perifericile si sunt in general subordonate perifericilor. Bufferele de date de iesire a perifericelor si semnalele de control sunt furnizate in pereche sau multiplexate. Cand un periferic este validat si activeaza pe pinul asociat, utilizarea acestui pin ca iesire este dezactivata. Pinul de intrare/iesire poate fi citit dar driverul de iesire pentru bitul portului paralel va fi dezactivat. Daca perifericul este validat dar nu activeaza pe pinul asociat, acest pin poate fi actionat de port.

Figură 2-27 Diagrama bloc a structurii unui port de intrare/iesire

Toti pinii portului au trei registre direct asociate lor, ca intrari/iesiri digitale. Registrul de directie a datelor (TRISx) determina care pin este intrare si care iesire. Daca bitul de directie a datelor este ‘1’ atunci pinul este intrare. Toti pinii portului sunt definiti ca intrari dupa reset. Citirea din port (PORTx), citeste pinii portului, cat timp scrierea la pinii portului, scrie latch-ul.

Modulul Timer1

Modulul Timer1 este un timer de 16 biti care poate servi ca numarator pentru ceasul de timp real sau opereaza ca timer/numarator liber. Timer1 poate opera in trei moduri:

timer pe 16 biti

numarator sincron pe 16 biti

numarator asincron pe 16 biti

Timer 1 mai suporta cateva caracteristici:

operare pe poarta timerului

prescaler selectabil

operarea timerului pe durata modului de inactivitate

intrerupere la potrivirea registrului perioada de 16 biti sau pe frontul descrescator al semnalului aplicat pe poarta externa

Figură 2-28 Diagrama bloc a modulului timer 1 pe 16 biti

Modulele Timer2/3, Timer4/5, Timer6/7 si Timer8/9

Modulele Timer2/3, Timer4/5, Timer6/7 si Timer8/9 sunt timere 32 biti care pot fi configurate ca opt timere independente pe 16 biti cu selectarea modului de operare.

Ca timere pe 32 biti, pot opera in trei moduri:

doua timere independente pe 16 biti (ex. Timer2 si Timer3) cu toate modurile de operare pe 16 biti (cu exceptia modului numarator asincron)

timer pe 32 biti

numarator sincron pe 32 biti

In plus, mai suporta urmatoarele caracteristici:

operare pe poarta timerului

prescaler selectabil

operarea timerului pe durata modului de inactivitate

intrerupere la potrivirea registrului perioada de 32 biti

baza de timp pentru modulele Input Capture si Output Compare (numai Timer2 si Timer3)

Individual, toate cele opt timere pe 16 biti pot functiona ca timere sau numaratoare sincrone. Modurile de operare sunt determinate prin setarea bitilor corespunzatori din registrele de control.

Pentru operarea ca timer/numarator pe 32 biti, Timer2, Timer4, Timer6 si Timer8 este cuvantul cel mai putin semnificativ iar Timer3, Timer5, Timer7 si Timer9 este cuvantul cel mai semnificativ din timerul de 32 biti.

Figură 2-29 Diagrama bloc a modulului timer 2/3 pe 32 biti

Captura intrarii

Modulul de captura a intrarii este folositor in aplicatii unde este necesara masurarea frecventei (perioadei) si impulsului. Controlerele dsPIC30F4011 suporta pana la opt canale de captura a intrarii.

Modulul de captura a intrarii face capturi pe 16 biti in registrul baza de timp selectat atunci cand un eveniment apare pe pinul ICx. Evenimentele care pot cauza captura sunt urmatoarele:

Modul captura eveniment simplu

captura in timer la fiecare front crescator al pinului de intrare ICx

captura in timer la fiecare front descrescator al pinului de intrare ICx

Captura in timer la fiecare front (crescator si descrescator)

Moduri de captura a evenimentului cu prescaler

captura in timer la fiecare al 4-lea front crescator al pinului de intrare ICx

captura in timer la fiecare al 4-lea front descrescator al pinului de intrare ICx

Fiecare canal de captura a intrarii poate selecta pentru baza de timp unul din cele doua timere pe 16 biti (Timer2 sau Timer3). Timerul selectat poate utiliza ceasul intern sau extern.

Alte caracteristici operationale sunt:

revenirea din inactivitate in cazul aparitiei evenimentului pe pinul de captura

intrerupere in cazul evenimentului de captura

buffer FIFO de 4 cuvinte pentru valorile capturate

Figură 2-30 Diagrama bloc a modului de captura a intrarii

Convertorul analog-digital pe 10 biti

Controlerele dsPIC30F4011 au pana la 32 canale de intrare analog-digitale. Deasemenea, aceste controlere au pana la doua module ADC, fiecare cu registrele de functii speciale proprii.

Bitul AD12B (ADxCON1<10>) permite fiecarui modul ADC sa fie configurate ca si convertor analog-digital pe 10 biti cu conversia a 4 esantioane in acelasi timp sau ca ADC pe 12 biti cu conversia unui esantion.

Caracteristici principale:

conversie prin aproximatii succesive

viteze de conversie de pana la 1.1 Msps pentru convertorul pe 10 biti si de 500 ksps pentru cel de 12 biti

pana la 32 pini de intrare analogici

pini pentru tensiune de referinta externa

esantionare simultana de pana la patru intrari analogice pentru convertorul de 10 biti

mod de scanare a canalelor automata

sursa de declansare a conversiei selectabila

moduri de umplere a bufferului selectabile

patru optiuni de aliniere a rezultatului (cu semn/fara semn, fractii/intregi)

moduri de operare pe durata de inactivitate

In functie de numarul de pini ai controlerului, convertorul analog-digital poate avea pana la 32 de intrari analogice, numerotate de la AN0 pana la AN31. In plus, au doua intrari analogice pentru conectarea tensiunii de referinta externe. Aceste intrari ale tensiunii de referinta pot fi partajate cu alte intrari analogice.

Diagrama bloc a convertorului analog-digital este prezentata in figura urmatoare.

Figură 2-31 Diagrama bloc a modulului ADC

Initializarea convertorului analog digital

Pentru configurarea convertorului analog-digital trebuie executati urmatorii pasi:

Configurarea modulului ADC:

Selectarea pinilor portului ca intrari analogice (ADxPCFGH<15:0> sau ADxPCFGL<15:0>)

Selectarea sursei tensiunii de referinta in functie de intervalul probabil al intrarilor analogice (ADxCON2<15:13>)

Selectarea ceasului de conversie (ADxCON3<5:0>)

Determinarea numarului de canale folosite (ADxCON2<9:8> si ADxCON<15:0>)

Selectarea secventei esantion/conversie (ADxCON1<7:5> si ADxCON3<12:8>)

Selectarea numarului de rezultate ale conversiei prezente in buffer (ADxCON1<15>)

Pornirea modulului ADC (ADxCON1<15>)

Configurarea intreruperii ADC (daca este necesara):

Stergerea bitului AdxIF

Selectarea prioritatii intreruperii ADC

2.4.SCHEMA CIRCUITULUI

Pornind de la microcontroler, prin definirea intrărilor și a ieșirilor avem:

Figură 2-32 Intrari si iesiri microcontroler

Tabelul de mai jos reprezintă un extras din codul sursă.

Tabel 2. 5 Definire intrări și ieșiri

Figură 2-33 Conexiunea releelor și a electrovalvelor

Figură 2-34 Conexiunile motoarelor pompelor, boilerului și trapei de acces în stația de hrănire

Figură 2-35 Conexiunile releelor cu led de stare

Componentele electronice din figura 2.33 sunt:

Diode D1, …, D18: 1N4001

Rezistențe R1, R3, …, R35: 5kΩ

Rezistențe R2, R4, …, R36: 2K7Ω

Tranzistori T1, T2, …, T18: KSP2222A

Relee K1, K2, …, K18: DC12V, 0.3A/125VAC, 0.3A/110VDC, 1A/30VDC

Figură 2-36 Conexiunea debitmetrului

Componentele electronice din figura 2.34 sunt:

Rezistența R37: 6k8Ω

Rezistența R38: 1KΩ

Tranzistor T19: KSP2222A

Condensator C1: 1µF

Figură 2-37 Conexiunea senzorului de temperatură

Componentele electronice din figura 2.35 sunt:

Rezistența R39: 20kΩ

Rezistența R40: 3K3Ω

Condensator C2: 10µF

Figură 2-38 Modul comunicatie DsPIC – PC

Componentele electronice din figura 2.36 sunt:

Transceiver RS232: MAX232N

Condensator C1, …, C6: 1µF

Figură 2-39 Modul RfID pentru identificarea vițeilor

Figură 2-40 Cablajul electronic

APLICATIA PROPRIU ZISA – MENIURI ȘI OPTIUNI

Acest capitol cuprinde descrierea software-ului creat, fiind prezentată interfața utilizator (GUI Graphical User Interface), aici regăsindu-se și schema funcțională a sistemului. Interfața utilizatorului (UI) reprezintă interacțiunea om-calculator și este prezentată în imaginea de mai jos fiind disponibilă în doua variante: cu ecran tactil sau ecran cu tastatură și mouse. Scopul acestei interacțiuni este de a permite operarea și controlul efectiv al sistemului de hrănire automată a vițeilor, de către utilizator.

Figură 3-1 Interfața utilizatorului UI

Lista componentelor ce se regăsesc în interfața utilizatorului

Intrări:

Senzor temperatura pentru laptele preparat (TH1)

Senzor temperatura pentru laptele preparat la tetina (TH2)

Debitmetru apa mixer (DM1)

Debitmetru lapte preparat (DM2)

Debitmetru lapte preparat (DM3)

Sonda nivel minim mixer (opțional)

Ieșiri:

Electrovalva 1 (EV1)

Electrovalva 2 (EV2)

Electrovalva 3 (EV3)

Electrovalva 4 (EV4)

Electrovalva 5 (EV5)

Electrovalva 6 (EV6)

Electrovalva 7 (EV7)

Electrovalva 8 (EV8)

Electrovalva 9 (EV9)

Electrovalva 10 (EV10)

Electrovalva 11 (EV11)

Electrovalva 12 (EV12)

Pompă de dozaj peristaltică 1 (PP1)

Pompă de dozaj peristaltică 2 (PP2)

Pompă de dozaj peristaltică 3 (PP3)

Pompa alimentare mixer (P1)

Pompa de transfer, alimentare boluri (P2)

Pompa evacuare apa după spălare instalație (P3)

Pompa evacuare apa după spălare instalație (P4)

Motor alimentare lapte praf

Motor mixer

Rezistenta de încălzire apa pentru prepararea laptelui (R1)

Sistemul de hranire automata a viteilor conceput si creat are doua statii de hranire cu biberon. In timp real, pe afișaj, se pot citi urmatoarele informatii pentru cele 2 statii:

Ultima vizita

Urmatoare vizita

Concentrat 1

Concentrat 1

Aditiv pompa dozaj 1

Aditiv pompa dozaj 2

Aditiv pompa dozaj 3

Rata de hranire

Timp de hranire

Respectiv

ID-ul vitelului

Grupa

Varsta

Cantitate lapte stabilita

Cantitate lapte consumata

Status

3.1.INTERFAȚA DE DIAGNOSTICARE

Aplicația permite verificarea echipamentului prin accesarea butonului „Diagnose” de unde se pot testa echipamentele individual în „ServiceMode”. Astfel poate fi calibrat debitmetrul prin setarea numărului de impulsuri (52224 imp/261120 ml), poate fi modificat timpul de funcționare a pompelor de dozare 1-3, pornirea sau oprirea pompelor, motoarelor, durata de funcționare a releelor, electrovalvelor sau inchiderea/deschiderea porții de acces la tetină.

Figură 3-2 Meniul „Diagnose”

3.2.INTERFAȚA PENTRU SETĂRI

Din meniul „Settings” se pot ajusta parametrii sistemului de hrănire automata a vițeilor,

parametrii procesului de hrănire și parametrii de calibrare ai sistemului

Figură 3-3 Meniul „Settings”

1.Parametrii sistemului de hrănire automată a vițeilor:

Debit pompa de apa [m/s]

Debit pompa transfer [m/s]

Debit apa rece [m/s]

Debit apa calda[m/s]

Debit pompa dosare 1, 2 si 3 [ml/min]

Debit lapte praf 1 si 2 [g/min]

Timp amestecare mixer initial [s]

Timp amestecare mixer final [s]

Debitmetru lichid transferat [imp/l]

Debitmetru lichid evacuat [imp/l]

2.Parametrii procesului de hrănire:

Începutul programului de hrănire [ora/24]

Încheierea programului de hrănire [ora/24]

Interval între hrăniri [ora/24]

3.Parametrii de calibrare ai sistemului:

Timp între citirile de temperatura [s]

Durata de deschidere electrovalve [s]

3.3.INTERFAȚA ALARMELOR

Următorul meniu este cel dedicat alarmelor ce permite vizualizarea cauzelor lor, frecvenței de aparitie, istoricului lor și tot de aici se pot seta parametrii acestora.

Figură 3-4 Meniul „Alarms”

Lista de alarme prestabilite ale sistemului se regaseste mai jos și conține:

-alarme parametri boiler

-alarme alimentare cu apă rece

-alarme referitoare la temperatura si parametrii amestecului

-alarmele debitmetrelor

-alarme pompe

-alarme presiune apa

-alarme identificare vitei recunoastere RfID

-alarme parametrii hranire

Figură 3-5 Fereastra cu lista de alarme și ID corespondent

Și prin dublu click pe alarmă se deschide meniul de configurare individuală a fiecărei alarme:

Figură 3-6 Fereastra „Alarm Configuration”

3.4.INTERFAȚA PENTRU IDENTIFICARE TAGURI RfID

Meniul “RfID Tags” pentru adăugarea sau eliminarea viteilor în lista lotului corespondent stației de hranire. Accesul în perimetrul statiei de hranire se face pe bază de taguri personalizate de tip RfID (Radio frequency Identification) recunoscute când sunt apropiate de cititoarele de proximitate (antene) instalate la intrarea în stația de hrănire.

Figură 3-7 Meniul “RfID Tags”

Cititoarele de proximitate din spațiile de acces la stațiile de hrănire sunt monitorizate de calculator, ce salvează într-o bază de date toată activitatea legată de intrările/ieșirile vițeilor. În acest mod se poate obține un control strict și precis asupra activității desfășurate. Sistemul permite alcătuirea de grupuri în funcție de rasă, vârstă sau starea de sănatate.

Avantajele sistemului:

asigură un control strict al accesului în stația de hrănire;

se poate vedea o situație actualizată în timp real, a intrărilor/ieșirilor vițeilor;

asigură memorarea tuturor intrărilor/ieșirilor;

folosind datele din baza de date utilizatorul poate vedea timpul petrecut în stația de hrănire individual pe fiecare vițel și defalcat pe ore sau stație de hrănire.

Avantajele utilizării cititoarelor de proximitate și tag-urilor de tip RfID:

fiabilitate crescută datorită lipsei contactului mecanic direct dintre cititor și card;

construcție robustă Tagul este intr-o carcasa de plastic pe urechea vițelului;

algoritmul de adăugare/ștergere este foarte simplu – prin accesarea meniul “RfID Tags”;

fiecare Tag este caracterizat de un cod unic.

Stația de hrănire cu tetină și clapetă pentru îndepărtarea accesului la tetină dupa încheierea alăptarii:

Figură 3-8 Stația de hrănire cu clapeta în pozitie acces permis la tetină

3.5.INTERFAȚA BAZEI DE DATE

Meniul „Database” permite accesul în baza de date unde se pot vedea activitățile fiecărui lot de vitei, respectiv fiecărui vițel în parte, vârsta, ultima vizită, următoarea vizită estimată și rețeta de hrănire (concentrat 1, concentrat 2, amestec, aditiv 1, aditiv 2, aditiv 3, stare vițel).

Figură 3-10 Meniul ”Calves Database”

Tot din acest meniu se pot adăuga, șterge sau modifica vițeii prin accesarea “Add Calf”

Figură 3-11 Fereastra “Add Calf”

Prin adăugarea unui vițel nou se stabilește data la care acesta a fost introdus, vârsta vițelului, câte zile va fi hrănit și după ce rețetă, grupul/rasa din care face parte și selectarea rețetei de hrănire.

Din pagina inițială „Database” prin apăsarea butonului „Recipes” se pot crea/stabili rețetele individuale de hrănire a vițeilor, respectiv modifica/ajusta rețetele existente în funcție de informațiile furnizorului / noului furnizor de lapte praf.

Figură 3-12 Fereastra ”Recipes”

Cantitatea de concentrat și aditivi se prepară luând în considerare următorii factori:

greutatea vițelului,

viteza de baut,

frecventa cu care bea,

vârsta vițelului,

agitat sau nu în timpul hrănirii,

grup.

CONCLUZII

În perioada de testare a sistemului automat de hrănire viței, s-a verificat faptul că hrănirea se face într-o manieră controlată, sistemul astfel contruit permițând stabilirea numărului meselor și urmărirea cantității consumate de fiecare vițel. Cel mai important aspect fiind reprezentat de posibilitatea și ușoara accesibilitate de a modifica rețetele de hrănire accesând meniul software în funcție de recomandările furnizorului de lapte praf (chiar în situația utilizării mai multor tipuri de lapte praf de la diverși furnizori).

In timpul utilizarii acestui prototip s-a observat că în condiții de umiditate atmosferică crescută laptele praf se umezește si aderă de pereții cuvei de inox și nu alunecă către transportorul melcat. In aceste condiții palele șnecului nu se încarcă cu lapte praf și deoarece cantitatea de lapte preparat este calculată prin numărul de rotiri ale șnecului se impune introducerea unui dispozitiv de cântărire poziționat sub mixer. Cu ajutorul acestui dispozitiv se poate măsura încă o dată cantitatea de apa si de lapte praf.

Acest sistem automat poate fi utilizat la ferme de orice dimensiuni permițand introducerea de stații suplimentare de hrănire, de asemenea este un sistem adaptabil ce permite vițeilor hrănirea în ritmul lor natural, de mai multe ori în aceeași zi și în același timp previne transmiterea bolilor de la un vițel la altul prin spălarea cu apă fierbinte a tetinelor urmată de o clătire a stației de alăptare.

ANEXA 1

Densitatea apei:

0 grC – 0.9998425 g/cm3

100 grC – 0.9583665 g/cm3

––––––––––––––––––––––––––––––––––

var table = new Array(

0.998120,0.998398,0.998650,0.998877,0.999080,0.999259,0.999417,0.999553,0.999669,0.999765,

0.9998425,0.9999015,0.9999429,0.9999672,0.9999750,0.9999668,0.9999432,0.9999045,0.9998512,0.9997838,

0.9997026,0.9996018,0.9995004,0.9993801,0.9992474,0.9991026,0.9989460,0.9987779,0.9985986,0.9984082,

0.9982071,0.9979955,0.9977735,0.9975415,0.9972995,0.9970479,0.9967867,0.9965162,0.9962365,0.9959478,

0.9956502,0.9953440,0.9950292,0.9947060,0.9943745,0.9940349,0.9936872,0.9933316,0.9929683,0.9925973,

0.9922187,0.9918327,0.9914394,0.9910388,0.9906310,0.9902162,0.9897944,0.9893657,0.9889303,0.9884881,

0.9880393,0.9875839,0.9871220,0.9866537,0.9861791,0.9856982,0.9852111,0.9847178,0.9842185,0.9837132,

0.9832018,0.9826846,0.9821615,0.9816327,0.9810981,0.9805578,0.9800118,0.9794603,0.9789032,0.9783406,

0.9777726,0.9771991,0.9766203,0.9760361,0.9754466,0.9748519,0.9742520,0.9736468,0.9730366,0.9724212,

0.9718007,0.9711752,0.9705446,0.9699091,0.9692686,0.9686232,0.9679729,0.9673177,0.9666576,0.9659927,

0.9653230,0.9646486,0.9639693,0.9632854,0.9625967,0.9619033,0.9612052,0.9605025,0.9597951,0.9590831,

0.9583665,0.957662,0.956937,0.956207,0.955472,0.954733,0.953989,0.953240,0.952488,0.941730

);

function waterdensity(t)

{

var i = Math.floor(t);

var p = t – i;

var p2m1 = p * p – 1.0;

var p2m4 = p2m1 – 3.0;

i += 10;

return p2m1*p*(p-2)*table[i-2]/24.0 – (p-1)*p*p2m4*table[i-1]/6.0 + p2m1*p2m4*table[i]/4.0 – (p+1)*p*p2m4*table[i+1]/6.0 + p2m1*p*(p+2)*table[i+2]/24.0;

}

ANEXA 2

În anexa 2 se regăsesc detaliile fișierelor ce conțin și codul sursă. Mediul de dezvoltare utilizat a fost MPLAB C30 v2.01.00, limbajul de programare C.

Fișier ”delay.h”:

#define Fcy 16000000 // Fcy = Fosc/4 (Fosc = 64MHz)

void Delay( unsigned int delay_count );

void Delay_Us( unsigned int delayUs_count );

#define Delay200uS_count (Fcy * 0.0002) / 1080

#define Delay_1mS_Cnt (Fcy * 0.001) / 2950

#define Delay_2mS_Cnt (Fcy * 0.002) / 2950

#define Delay_5mS_Cnt (Fcy * 0.005) / 2950

#define Delay_15mS_Cnt (Fcy * 0.015) / 2950

#define Delay_50mS_Cnt (Fcy * 0.05) / 2950

#define Delay_100mS_Cnt (Fcy * 0.1) / 2950

#define Delay_1S_Cnt (Fcy * 1) / 2950

Fișier ”delay.c”:

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

*

* Simple Delay Routines

*

*********************************************************************

* Author: Vasilache Radu, Mugurel Caracostea

* FileName: delay.c

* Dependencies: delay.h

* Processor: dsPIC33F

* Complier: MPLAB C30 v2.01.00 or higher

*

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

#include "delay.h"

unsigned int temp_count;

void Delay( unsigned int delay_count )

{

temp_count = delay_count +1;

asm volatile("outer: dec _temp_count");

asm volatile("cp0 _temp_count");

asm volatile("bra z, done");

asm volatile("do #3200, inner" );

asm volatile("nop");

asm volatile("inner: nop");

asm volatile("bra outer");

asm volatile("done:");

}

void Delay_Us( unsigned int delayUs_count )

{

temp_count = delayUs_count +1;

asm volatile("outer1: dec _temp_count");

asm volatile("cp0 _temp_count");

asm volatile("bra z, done1");

asm volatile("do #1500, inner1" );

asm volatile("nop");

asm volatile("inner1: nop");

asm volatile("bra outer1");

asm volatile("done1:");

}

Fișier ”common.h”:

void __builtin_btg(unsigned int *, unsigned int);

Fișier ”uart2.h”:

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

*

* UART Driver for dsPIC30.

*

*****************************************************************************

* FileName: uart2.c

* Dependencies:

* Processor: dsPIC30

* Compiler: MPLAB C30

* Linker: MPLAB LINK30

* A simple UART polled driver

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

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

* DEFINITIONS

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

#define STX 0x0F

#define ETX 0x04

#define DLE 0x05

// Baudrate

#define BAUDRATE2 9600

Fișier ”uart2.c”:

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

* UART Driver for dsPIC30.

*****************************************************************************

* FileName: uart2.c

* Processor: dsPIC30

* Compiler: MPLAB C30

* Linker: MPLAB LINK30

* A simple UART polled driver

* Author Date Comment

*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* Vasilache Radu, Mugurel Caracostea 05/14/09 ………

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

#include "p30f4011.h"

#include "uart2.h"

#include "delay.h"

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

* U2BRG register value and baudrate mistake calculation

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

#define BAUDRATEREG2 Fcy/BAUDRATE2/16-1

#if BAUDRATEREG2 > 255

#error Cannot set up UART2 for the Fcy and BAUDRATE.\

Correct values in main.h and uart2.h files.

#endif

short U2FlagPckRcv = 0;

unsigned char U2RXBuffer[256];

short U2FlagDLE = 0;

short U2FlagSave = 0;

short CountSTX = 0;

short U2RXBuffIndex = 0;

short U2RXBuffLen = 0;

unsigned int ChkSum = 0;

/*

; Incoming data format:

;

; <STX><STX><DATA><CHKSUM><ETX>

; / \

; ________/ \____________________________

; / \

; <COMMAND><DLEN><ADDRL><ADDRH><ADDRU><DATA>…

;

; Definitions:

;

; STX – Start of packet indicator

; ETX – End of packet indicator

; LEN – Length of incoming packet

; DATA – General data up to 255 bytes

; CHKSUM – The 8-bit two's compliment sum of LEN & DATA

; COMMAND – Base command

; DLEN – Length of data associated to the command

; ADDR – Address up to 24 bits

; DATA – Data (if any)

;

; Commands:

;

; RD_VER 0x00 Read Version Information

;

*/

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

* Function: InitUART2

* Precondition: None.

* Overview: Setup UART2 module.

* Input: None.

* Output: None.

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

void InitUART2() {

// Load a value into Baud Rate Generator. Example is for 9600.

// See section 19.3.1 of datasheet.

// U2BRG = (Fcy/(16*BaudRate))-1

// U2BRG = (40M/(16*9600))-1 // 40Mhz osc, 9600 Baud

// U2BRG = 260

U2BRG = BAUDRATEREG2;

IFS1bits.U2TXIF = 0; // Clear the Transmit Interrupt Flag

IEC1bits.U2TXIE = 1; // Enable Transmit Interrupts

IFS1bits.U2RXIF = 0; // Clear the Recieve Interrupt Flag

IEC1bits.U2RXIE = 1; // Enable Recieve Interrupts

IPC6bits.U2TXIP = 4;

IPC6bits.U2RXIP = 4;

// configure U2MODE

U2MODE = 0x8000;

// configure U2STA

U2STA = 0x0400;

}

void __attribute__ ((interrupt, no_auto_psv)) _U2RXInterrupt(void) {

char RXTemp;

RXTemp = U2RXREG;

if (CountSTX < 2) {

if (RXTemp == STX) {

CountSTX++;

ChkSum = 0;

U2RXBuffIndex = 0;

} else {

CountSTX = 0;

U2FlagDLE = 0;

U2FlagSave = 0;

U2FlagPckRcv = 0;

}

} else {

switch (RXTemp) {

case DLE:

if (U2FlagDLE == 1)

U2FlagSave = 1;

else {

U2FlagDLE = 1;

U2FlagSave = 0;

}

break;

case STX:

if (U2FlagDLE == 1)

U2FlagSave = 1;

else {

CountSTX = 0;

U2FlagSave = 0;

}

break;

case ETX:

if (U2FlagDLE == 1)

U2FlagSave = 1;

else {

U2FlagPckRcv = 1;

U2RXBuffLen = U2RXBuffIndex;

CountSTX = 0;

U2FlagDLE = 0;

U2FlagSave = 0;

}

break;

default:

U2FlagSave = 1;

}

if (U2FlagSave == 1) {

U2FlagDLE = 0;

ChkSum += RXTemp;

U2RXBuffer[U2RXBuffIndex] = RXTemp;

U2RXBuffIndex++;

if (U2RXBuffIndex >= 255) {

CountSTX = 0;

U2FlagDLE = 0;

U2FlagSave = 0;

U2FlagPckRcv = 0;

}

}

}

IFS1bits.U2RXIF = 0;

}

void __attribute__ ((interrupt, no_auto_psv)) _U2TXInterrupt(void) {

IFS1bits.U2TXIF = 0;

}

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

* Function: UART2PutChar

* Precondition: UART2Init must be called before.

* Overview: Wait for free UART transmission buffer and send a byte.

* Input: Byte to be sent.

* Output: None.

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

void UART2PutChar(char Ch){

// wait for empty buffer

while(U2STAbits.UTXBF == 1);

U2TXREG = Ch;

}

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

* Function: UART2IsPressed

* Precondition: UART2Init must be called before.

* Overview: Check if there's a new byte in UART reception buffer.

* Input: None.

* Output: Zero if there's no new data received.

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

char UART2IsPressed()

{

if(IFS1bits.U2RXIF == 1)

return 1;

return 0;

}

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

* Function: UART2GetChar

* Precondition: UART2Init must be called before.

* Overview: Wait for a byte.

* Input: None.

* Output: Byte received.

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

char UART2GetChar(){

char Temp;

while(IFS1bits.U2RXIF == 0);

Temp = U2RXREG;

IFS1bits.U2RXIF = 0;

return Temp;

}

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

* Function: UART2PutDec

* Precondition: UART2Init must be called before.

* Overview: This function converts decimal data into a string and outputs it into UART.

* Input: Binary data.

* Output: None.

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

void UART2PutDec(unsigned char Dec){

unsigned char Res;

Res = Dec;

if(Res/100)

UART2PutChar(Res/100+'0');

Res = Res – (Res/100)*100;

if(Res/10)

UART2PutChar(Res/10+'0');

Res = Res – (Res/10)*10;

UART2PutChar(Res+'0');

}

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

* Function: UART2PutDec

* Precondition: UART2Init must be called before.

* Overview: This function converts decimal data into a string and outputs it into UART.

* Input: Binary data.

* Output: None.

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

void SendPacket(char PacketData[], short NumOfBytes)

{

unsigned int PacketCount;

unsigned int Checksum = 0;

unsigned int BytesWritten;

char DataByte;

//Send the start condition

DataByte = STX;

for(PacketCount = 0; PacketCount < 2; PacketCount++){

UART2PutChar(DataByte);

}

//Send the packet data and stuff byte if necessary

for(PacketCount = 0; PacketCount < NumOfBytes; PacketCount++)

{

switch (PacketData[PacketCount])

{

case STX:

case ETX:

case DLE:

{

DataByte = DLE;

UART2PutChar(DataByte);

break;

}

}

DataByte = PacketData[PacketCount];

Checksum = Checksum + (unsigned int)DataByte;

UART2PutChar(DataByte);

}

//Send the checksum

DataByte = (char)(((~(Checksum)) + 1) & 255);

switch (DataByte)

{

case STX:

case ETX:

case DLE:

{

DataByte = DLE;

UART2PutChar(DataByte);

break;

}

}

DataByte = (char)(((~(Checksum)) + 1) & 255);

UART2PutChar(DataByte);

//Send the stop condition

DataByte = ETX;

UART2PutChar(DataByte);

}

Fișier ”main.c”:

/* SOFTWARE LICENSE AGREEMENT:

//

// Revision History

//

// July/5/2009 – first version

// Author: Vasilache Radu, Mugurel Caracostea

//–––––––––––––––––––––––-

*/

#include "p30f4011.h"

#include "delay.h"

//–––––––––Device Configuration––––––––

//_FOSC(CSW_FSCM_OFF & XT_PLL4);

_FOSC(CSW_FSCM_OFF & XT_PLL8);

_FWDT(WDT_OFF);

_FBORPOR(PBOR_ON & BORV_20 & PWRT_64 & MCLR_EN);

//–––––––––––––––––––––––-

short g_MilkProcessingFlag = 0;

unsigned int g_ui100msCounter0 = 0;

unsigned int g_ui100msCounter1 = 0;

unsigned int g_ui100msCounter2 = 0;

unsigned int g_uiCounterSubStep = 0;

unsigned int g_uiFeedingTimeout = 150; // 15s demo

unsigned int g_uiTimePowder1;

unsigned int g_uiTimePowder2;

unsigned int g_uiTimeDosingPump1; //

unsigned int g_uiTimeDosingPump2; //

unsigned int g_uiTimeDosingPump3; //

unsigned int g_uiTimeTransferPump; //

unsigned int g_uiTimeColdWaterInitial;

unsigned int g_uiTimeHotWaterInitial;

unsigned int g_uiTimeColdWaterFinal;

unsigned int g_uiCounterFlowmeter1 = 0;

unsigned int g_uiImpFlowmeterCalc1; //

unsigned int g_uiImpFlowmeterTransf1; //

unsigned int g_uiImpFlowmeterFeed1; //

unsigned int g_uiImpFlowmeter2; //

unsigned int g_uiMixingTimeInitial; // s * 10

unsigned int g_uiMixingTimeFinal; // s * 10

unsigned int g_uiFlowmeterCounter;

unsigned int g_uiFlowmeterCounterOld;

unsigned int g_uiDiagOpenRelayDuration;

unsigned char g_ucDiagRelayNumber;

char g_RFIDTagFlag = 0;

char g_RFIDTagResetFlag = 0;

char g_CaptureCompletedFlag = 0;

char g_ByteCapture = 0;

unsigned char g_RFID_DataCaptureTemp[66];

unsigned char g_RFID_DataCapture[64];

unsigned char g_RFIDCurrentTag[5];

unsigned short g_RFID_DataCntr = 0;

unsigned short g_RFID_CaptureCompletedFlag = 0;

unsigned int g_uiRFID_Fres; // Antenna circuit resonant frequency

unsigned short g_RFID_LineParityCheck = 0;

unsigned short g_RFID_ColumnParityCheck = 0;

unsigned short g_uiStateFeederMachine = 0;

unsigned short g_uiTaskProcessingStep = 0;

unsigned short g_ByteCounter = 0;

unsigned short g_StackCounter = 0;

short g_StartCaptureFlag = 0;

unsigned int g_uiTmr2 = 0;

unsigned long g_ulDensityMixtWater;

unsigned long g_ulDensityColdWater;

unsigned long g_ulDensityHotWater;

unsigned int g_uiVolColdWater;

unsigned int g_uiVolHotWater;

int g_iTempSensorResult;

int g_iTempSensorResultOld;

// variables for cleaning

unsigned int g_uiTimeHotWaterCleaning1 = 20; // 2s

unsigned int g_uiTimeHotWaterCleaning2 = 20; // 2s

unsigned int g_uiTimeColdWaterCleaning1 = 20;

unsigned int g_uiTimeColdWaterCleaning2 = 20;

unsigned int g_uiTimeTransferPumpCleaning1 = 30; // 3s

unsigned int g_uiTimeTransferPumpCleaning2 = 30; // 3s

unsigned int g_uiTimeEvacWaterCleaning1 = 50;

unsigned int g_uiTimeEvacWaterCleaning2 = 50;

unsigned int g_uiTimeEvacWaterCleaning3 = 50;

unsigned int g_uiTimeEvacWaterCleaning4 = 50;

unsigned int g_uiTimeReadWaterTemp = 30;

// variables for calibrate

unsigned int g_uiTimeWaterCalibrateInitial; //

unsigned int g_uiTimeWaterCalibrateFinal; // 2s

unsigned int g_uiTimeReadingTempsInitial;

unsigned int g_uiTimeReadingTempsFinal;

unsigned char g_uiTimeTransferPumpCalibrate1 = 30; // 3s

unsigned char g_uiTimeTransferPumpCalibrate2 = 30; // 3s

unsigned char g_uiTimeEvacWaterCalibrate1 = 50;

unsigned char g_uiTimeEvacWaterCalibrate2 = 50;

unsigned char g_uiTimeEvacWaterCalibrate3 = 50;

unsigned char g_uiTimeEvacWaterCalibrate4 = 50;

#define TIME_TRANSFERPUMP_CALIBRATE 100 // seconds / 10

#define TIME_EVACUATE_CALIBRATE 900 // seconds / 10

#define TIME_READING_FLOWMETER_CALIBRATE 10 // seconds / 10

#define TIME_READING_FLOWMETER_TRANSFERPUMP 10 // seconds / 10

#define TIMEOUT_TRANSFERPUMP 100

#define TIME_READING_FLOWMETER_EVACUATE 20 // seconds / 10

#define TIMEOUT_EVACUATE 900

#define TIME_READING_FLOWMETER_FEEDING 30 // seconds / 10

#define TIMEOUT_FEEDING 6000 // 10 min

// Relay #1 – RB0

// Relay #2 – RB1

// Relay #3 – RB2

// Relay #4 – RB3

// Relay #5 – RB4

// Relay #6 – RB8

// Relay #7 – RB6

// Relay #8 – RD3

// Relay #9 – RC13

// Relay #10 – RC14

// Relay #11 – RE3

// Relay #12 – RE5

// Relay #13 – RE0

// Relay #14 – RE1

// Relay #15 – RE2

// Relay #16 – RF0

// Relay #17 – RE4

// Relay #18 – RF1

// RDY/CLK – RD0 (INT1)

// SHD – RD2

// DEMOD_OUT – RF6

#define START_FEEDWATERPUMP LATBbits.LATB0 = 1; // RELAY #1

#define STOP_FEEDWATERPUMP LATBbits.LATB0 = 0;

#define START_TRANSFERPUMP LATBbits.LATB1 = 1; // RELAY #2

#define STOP_TRANSFERPUMP LATBbits.LATB1 = 0;

#define START_MIXERMOTOR LATBbits.LATB2 = 1; // RELAY #3

#define STOP_MIXERMOTOR LATBbits.LATB2 = 0;

#define START_POWDERMILKMOTOR1 LATBbits.LATB3 = 1; // RELAY #4

#define STOP_POWDERMILKMOTOR1 LATBbits.LATB3 = 0;

#define START_POWDERMILKMOTOR2 LATBbits.LATB4 = 1; // RELAY #5

#define STOP_POWDERMILKMOTOR2 LATBbits.LATB4 = 0;

#define START_DOSINGPUMP1 LATBbits.LATB8 = 1; // RELAY #6

#define STOP_DOSINGPUMP1 LATBbits.LATB8 = 0;

#define START_DOSINGPUMP2 LATBbits.LATB6 = 1; // RELAY #7

#define STOP_DOSINGPUMP2 LATBbits.LATB6 = 0;

#define START_DOSINGPUMP3 LATDbits.LATD3 = 1; // RELAY #8

#define STOP_DOSINGPUMP3 LATDbits.LATD3 = 0;

#define START_BOILER LATCbits.LATC13 = 1; // RELAY #9

#define STOP_BOILER LATCbits.LATC13 = 0;

#define OPEN_CALFTRAPACCESS LATCbits.LATC14 = 1; // RELAY #10

#define CLOSE_CALFTRAPACCESS LATCbits.LATC14 = 0;

#define OPEN_EV1 LATEbits.LATE3 = 1; // RELAY #11 / 24V

#define CLOSE_EV1 LATEbits.LATE3 = 0;

#define OPEN_EV2 LATEbits.LATE5 = 1; // RELAY #12 / 24V

#define CLOSE_EV2 LATEbits.LATE5 = 0;

#define OPEN_EV3 LATEbits.LATE0 = 1; // RELAY #13 / 24V

#define CLOSE_EV3 LATEbits.LATE0 = 0;

#define OPEN_EV4 LATEbits.LATE1 = 1; // RELAY #14 / 24V

#define CLOSE_EV4 LATEbits.LATE1 = 0;

#define OPEN_EV5 LATEbits.LATE2 = 1; // RELAY #15 / 24V

#define CLOSE_EV5 LATEbits.LATE2 = 0;

#define OPEN_EV6 LATFbits.LATF0 = 1; // RELAY #16 / 220V

#define CLOSE_EV6 LATFbits.LATF0 = 0;

#define OPEN_EV7 LATEbits.LATE4 = 1; // RELAY #17 / 24V

#define CLOSE_EV7 LATEbits.LATE4 = 0;

#define OPEN_EV8 LATFbits.LATF1 = 1; // RELAY #18 / 220V

#define CLOSE_EV8 LATFbits.LATF1 = 0;

#define RFID_OP_MODE LATDbits.LATD2 = 0; // SHD = 0 operation mode

#define RFID_SLEEP_MODE LATDbits.LATD2 = 1; // SHD = 1 sleep mode

#define STATEMACHINE_INIT 0x00

#define STATEMACHINE_READY 0x01

#define STATEMACHINE_PROCESSING 0x02

#define STATEMACHINE_FEEDING 0x03

#define STATEMACHINE_CLEANING 0x04

#define STATEMACHINE_CALIBRATE 0x09

#define STATEMACHINE_ALARM 0xFF

unsigned int g_uimui = 0;

/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/

/* EXTERNAL VARIABLES */

/* */

// uart2.c

extern short U2FlagPckRcv;

extern unsigned char U2RXBuffer[256];

/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/

#define SAMPLINGRATE 8000

#define SAMPCOUNT (Fcy/SAMPLINGRATE)+1

//Functions:

//ADC_Init() is used to configure A/D to convert 16 samples of 1 input

//channel per interrupt. The A/D is set up for a sampling rate of 8KHz

//Timer3 is used to provide sampling time delay.

//The input pin being acquired and converted is AN7.

void ADC_Init(void)

{

//ADCON1 Register

//Set up A/D for Automatic Sampling

//Use Auto Start // Timer3 to provide sampling time

//Set up A/D conversrion results to be read in integer

//number format.

//All other bits to their default state

ADCON1bits.FORM = 0;

ADCON1bits.SSRC = 7;

ADCON1bits.ASAM = 1;

//ADCON2 Register

//Set up A/D for interrupting after 1 samples get filled in the buffer

//All other bits to their default state

ADCON2bits.SMPI = 15;

//ADCON3 Register

//We would like to set up a sampling rate of 8KHz

//Total Conversion Time= 1/Sampling Rate = 125 microseconds

//At 29.4 MIPS, Tcy = 33.9 ns = Instruction Cycle Time

//Tad > 667ns (for -40C to 125C temperature range)

//We will set up Sampling Time using Timer3 & Tad using ADCS<5:0> bits

//All other bits to their default state

//Let's set up ADCS arbitrarily to the maximum possible amount = 63

//So Tad = Tcy*(ADCS+1)/2 = 1.085 microseconds

//So, the A/D converter will take 14*Tad periods to convert each sample

// ADCON3bits.ADCS = 63;

ADCON3bits.SAMC = 31;

ADCON3bits.ADRC = 1;

//ADCHS Register

//Set up A/D Channel Select Register to convert AN7 on Mux A input

ADCHS = 0x0007;

// ADCHSbits.CH0NA = 0;

//ADCSSL Register

//Channel Scanning is disabled. All bits left to their default state

ADCSSL = 0x0000;

//ADPCFG Register

//Set up channels AN7 as analog input and configure rest as digital

//Recall that we configured all A/D pins as digital when code execution

//entered main() out of reset

ADPCFG = 0xFFFF;

ADPCFGbits.PCFG7 = 0;

//Clear the A/D interrupt flag bit

IFS0bits.ADIF = 0;

//Set the A/D interrupt enable bit

IEC0bits.ADIE = 1;

// Set A/D interrupt priority

IPC2bits.ADIP = 1;

//Turn on the A/D converter

//This is typically done after configuring other registers

ADCON1bits.ADON = 1;

}

//_ADCInterrupt() is the A/D interrupt service routine (ISR).

//The routine must have global scope in order to be an ISR.

//The ISR name is chosen from the device linker script.

void __attribute__((interrupt, no_auto_psv)) _ADCInterrupt(void)

{

int i;

i = (int) ADCBUF0 – g_iTempSensorResultOld;

i /= 2;

g_iTempSensorResult = g_iTempSensorResultOld + i;

g_iTempSensorResultOld = (int) ADCBUF0;

//Set the A/D interrupt disable bit

IEC0bits.ADIE = 0;

//Clear the A/D Interrupt flag bit or else the CPU will

//keep vectoring back to the ISR

IFS0bits.ADIF = 0;

}

/*–––––––––––––––––––––––

Function Name: Init_Timer2

Description: Initialize Timer2/3

Inputs: None

Returns: None

––––––––––––––––––––––––*/

void Init_Timer2_3( void )

{

/* ensure Timer 2/3 is in reset state */

T2CON = 0;

T3CON = 0;

T2CONbits.TCKPS = 0; //prescaler 1:1 (16MHz at Fosc=64MHz, Fcy = Fosc/4 = 16MHz, 62.5ns)

T3CONbits.TCKPS = 2; //prescaler 1:64 (250000Hz at Fosc=64MHz, Fcy = Fosc/4 = 16MHz, 4us)

/* reset Timer 2/3 interrupt flag */

IFS0bits.T2IF = 0;

IFS0bits.T3IF = 0;

/* set Timer 2/3 interrupt priority level to 4 */

IPC1bits.T2IP = 4;

IPC1bits.T3IP = 4;

/* enable Timer 2/3 interrupt */

IEC0bits.T2IE = 1;

IEC0bits.T3IE = 1;

PR2 = 20500; // (RFID Timer) (4*32clk*10us(100kHz))/0.0625us + 20

PR3 = 25000; // (Processing Milk) 100 ms with prescaler 1:64 and Fcy=16MHz

T2CONbits.TON = 1;

T3CONbits.TON = 1;

}

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

Function: int main(void)

PreCondition: None.

Input: None.

Output: None.

Side Effects: None.

Overview: main function of the application. Peripherals are initialized, and then, depending on the motor status (running or stopped) and if the push button is pressed, the motor is started or stopped. All other operations and state machines are performed with interrupts.

Note: None.

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

int main(void)

{

unsigned int i;

// Setting ports as outputs for relays

TRISB = 0xFEA0; // Set RB5 () and RB7 (temp sensor) as input

TRISCbits.TRISC13 = 0;

TRISCbits.TRISC14 = 0;

TRISDbits.TRISD3 = 0;

TRISE = 0xFFC0;

TRISFbits.TRISF0 = 0;

TRISFbits.TRISF1 = 0;

// Setting ports as inputs for interrupts

TRISEbits.TRISE8 = 1; // Set RE8 as input (INT0)

TRISDbits.TRISD1 = 1; // Set RD1 as input (INT2)

// Setting RFID pins

TRISDbits.TRISD2 = 0; // Set RD2 as output (SHD)

TRISFbits.TRISF6 = 1; // Set RF6 as input (DEMOD_OUT)

TRISDbits.TRISD0 = 1; // Set RD0 as input (INT1 – RDY/CLK)

// Configure UART0

TRISFbits.TRISF2 = 1; // Set RF2 as input (U1RX)

TRISFbits.TRISF3 = 0; // Set RF3 as output (U1TX)

// Configure UART1

TRISFbits.TRISF4 = 1; // Set RF4 as input (U2RX)

TRISFbits.TRISF5 = 0; // Set RF5 as output (U2TX)

/* Initializeaza intreruperea externa INT0. – flowmeter */

// INTCON2bits.INT0EP = 0; /* Intrerupere pe front pozitiv */

INTCON2bits.INT0EP = 1; /* Intrerupere pe front negativ */

IEC0bits.INT0IE = 1; /* Cerere de intrerupere activata */

IPC0bits.INT0IP = 5; /* Interrupt is priority is 5 (7 highest priority interrupt) */

IFS0bits.INT0IF = 0; /* Sterge flagul de intrerupere INT0IF */

/* Initializeaza intreruperea externa INT1. */

// INTCON2bits.INT1EP = 0; /* Intrerupere pe front pozitiv */

INTCON2bits.INT1EP = 1; /* Intrerupere pe front negativ */

IEC1bits.INT1IE = 1; /* Cerere de intrerupere activata */

IPC4bits.INT1IP = 6; /* Interrupt is priority is 6 (7 highest priority interrupt) */

IFS1bits.INT1IF = 0; /* Sterge flagul de intrerupere INT0IF */

Init_Timer2_3();

InitUART2(); // Initialize UART2 for 9600,8,N,1 TX/RX

ADC_Init();

g_uiStateFeederMachine = STATEMACHINE_READY;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep = 0;

for (;;) {

switch (g_uiStateFeederMachine) {

case STATEMACHINE_READY:

break;

case STATEMACHINE_PROCESSING:

if (g_RFID_CaptureCompletedFlag) {

for (i=1; i<5; i++) {

if (g_RFIDCurrentTag[i] != g_RFID_DataCapture[i]) {

g_uiTaskProcessingStep = 0;

g_RFIDTagFlag = 0;

break;

}

}

g_RFIDTagFlag = 1;

g_RFID_CaptureCompletedFlag = 0;

IEC1bits.INT1IE = 1; // Enable interrupt RFID DEMOD_OUT

}

break;

case STATEMACHINE_FEEDING:

break;

case STATEMACHINE_CLEANING:

break;

case STATEMACHINE_ALARM:

break;

}

if (U2FlagPckRcv == 1) {

U2FlagPckRcv = 0;

U2PckRcvProcessing();

}

} //end for

return 0;

}

/*–––––––––––––––––––––––

Function Name: U2PckRcvProcessing

Description: Processing Packet Received on UART2

Inputs: None

Returns: None

––––––––––––––––––––––––*/

void U2PckRcvProcessing()

{

int i;

unsigned int uiTemp;

switch (U2RXBuffer[0]) {

case 0x00: // test serial connection

SendPacket(U2RXBuffer, 3);

break;

case 0x0A: // State Feeder machine

U2RXBuffer[1] = g_uiStateFeederMachine;

U2RXBuffer[2] = g_uiTaskProcessingStep;

uiTemp = g_iTempSensorResult;

uiTemp >>= 8;

uiTemp &= 0x00FF;

U2RXBuffer[3] = (unsigned char) uiTemp;

uiTemp = g_iTempSensorResult;

uiTemp &= 0x00FF;

U2RXBuffer[4] = (unsigned char) uiTemp;

//Set the A/D interrupt enable bit

IEC0bits.ADIE = 1;

SendPacket(U2RXBuffer, 5);

break;

case 0x0B:

break;

case 0x10:

if (g_RFID_CaptureCompletedFlag) {

for (i = 0; i < 5; i++) {

U2RXBuffer[i] = g_RFID_DataCapture[i];

}

// U2RXBuffer[5] = (unsigned char) g_uiRFID_Fres >> 8;

// U2RXBuffer[6] = (unsigned char) g_uiRFID_Fres & 0x00FF;

uiTemp = g_uiRFID_Fres;

uiTemp >>= 8;

U2RXBuffer[5] = (unsigned char) uiTemp;

uiTemp = g_uiRFID_Fres;

uiTemp &= 0x00FF;

U2RXBuffer[6] = (unsigned char) uiTemp;

SendPacket(U2RXBuffer, 7);

g_RFID_CaptureCompletedFlag = 0;

IEC1bits.INT1IE = 1; // Enable interrupt RFID DEMOD_OUT

} else {

SendPacket(U2RXBuffer, 3);

}

break;

case 0x11:

if (g_RFID_CaptureCompletedFlag) {

for (i=0; i<5; i++) {

U2RXBuffer[i+1] = g_RFID_DataCapture[i];

g_RFIDCurrentTag[i] = g_RFID_DataCapture[i];

}

SendPacket(U2RXBuffer, 6);

g_RFID_CaptureCompletedFlag = 0;

IEC1bits.INT1IE = 1; // Enable interrupt RFID DEMOD_OUT

} else {

SendPacket(U2RXBuffer, 1);

}

break;

case 0x15:

if (U2RXBuffer[1]) {

// g_RFIDflag = 1;

} else {

// g_RFIDflag = 0;

}

SendPacket(U2RXBuffer, 2);

break;

case 0x20:

if (U2RXBuffer[1]) {

RFID_OP_MODE // SHD = 0 operation mode

} else {

RFID_SLEEP_MODE // SHD = 1 sleep mode

}

SendPacket(U2RXBuffer, 2);

break;

case 0x30:

switch (U2RXBuffer[1]) {

case 0x01:

LATBbits.LATB0 = U2RXBuffer[2];

break;

case 0x02:

LATBbits.LATB1 = U2RXBuffer[2];

break;

case 0x03:

LATBbits.LATB2 = U2RXBuffer[2];

break;

case 0x04:

LATBbits.LATB3 = U2RXBuffer[2];

break;

case 0x05:

LATBbits.LATB4 = U2RXBuffer[2];

break;

case 0x06:

LATBbits.LATB8 = U2RXBuffer[2];

break;

case 0x07:

LATBbits.LATB6 = U2RXBuffer[2];

break;

case 0x08:

LATDbits.LATD3 = U2RXBuffer[2];

break;

case 0x09:

LATCbits.LATC13 = U2RXBuffer[2];

break;

case 0x0A:

LATCbits.LATC14 = U2RXBuffer[2];

break;

case 0x0B:

LATEbits.LATE3 = U2RXBuffer[2];

break;

case 0x0C:

LATEbits.LATE5 = U2RXBuffer[2];

break;

case 0x0D:

LATEbits.LATE0 = U2RXBuffer[2];

break;

case 0x0E:

LATEbits.LATE1 = U2RXBuffer[2];

break;

case 0x0F:

LATEbits.LATE2 = U2RXBuffer[2];

break;

case 0x10:

LATFbits.LATF0 = U2RXBuffer[2];

break;

case 0x11:

LATEbits.LATE4 = U2RXBuffer[2];

break;

case 0x12:

LATFbits.LATF1 = U2RXBuffer[2];

break;

}

SendPacket(U2RXBuffer, 3);

break;

case 0x35:

g_ucDiagRelayNumber = U2RXBuffer[1];

g_uiDiagOpenRelayDuration = U2RXBuffer[2];

g_uiDiagOpenRelayDuration *= 10;

TMR3 = 0;

switch (g_ucDiagRelayNumber) {

case 0x01:

LATBbits.LATB0 = 1;

break;

case 0x02:

LATBbits.LATB1 = 1;

break;

case 0x03:

LATBbits.LATB2 = 1;

break;

case 0x04:

LATBbits.LATB3 = 1;

break;

case 0x05:

LATBbits.LATB4 = 1;

break;

case 0x06:

LATBbits.LATB8 = 1;

break;

case 0x07:

LATBbits.LATB6 = 1;

break;

case 0x08:

LATDbits.LATD3 = 1;

break;

case 0x09:

LATCbits.LATC13 = 1;

break;

case 0x0A:

LATCbits.LATC14 = 1;

break;

case 0x0B:

LATEbits.LATE3 = 1;

break;

case 0x0C:

LATEbits.LATE5 = 1;

break;

case 0x0D:

LATEbits.LATE0 = 1;

break;

case 0x0E:

LATEbits.LATE1 = 1;

break;

case 0x0F:

LATEbits.LATE2 = 1;

break;

case 0x10:

LATFbits.LATF0 = 1;

break;

case 0x11:

LATEbits.LATE4 = 1;

break;

case 0x12:

LATFbits.LATF1 = 1;

break;

}

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep = 0xF0;

SendPacket(U2RXBuffer, 3);

break;

case 0x38: // diag mode

g_uiTaskProcessingStep = 0xF1;

SendPacket(U2RXBuffer, 2);

break;

case 0x39: // exit diag mode / reset

g_uiTaskProcessingStep = 0;

SendPacket(U2RXBuffer, 2);

break;

case 0x40:

// __builtin_btg((unsigned int *)&LATA, 1);

break;

case 0x41:

g_uiTimePowder1 = U2RXBuffer[2];

g_uiTimePowder1 <<= 8;

g_uiTimePowder1 |= U2RXBuffer[3];

g_uiTimePowder2 = U2RXBuffer[4];

g_uiTimePowder2 <<= 8;

g_uiTimePowder2 |= U2RXBuffer[5];

g_uiTimeDosingPump1 = U2RXBuffer[6];

g_uiTimeDosingPump1 <<= 8;

g_uiTimeDosingPump1 |= U2RXBuffer[7];

g_uiTimeDosingPump2 = U2RXBuffer[8];

g_uiTimeDosingPump2 <<= 8;

g_uiTimeDosingPump2 |= U2RXBuffer[9];

g_uiTimeDosingPump3 = U2RXBuffer[10];

g_uiTimeDosingPump3 <<= 8;

g_uiTimeDosingPump3 |= U2RXBuffer[11];

g_uiTimeTransferPump = U2RXBuffer[12];

g_uiTimeTransferPump <<= 8;

g_uiTimeTransferPump |= U2RXBuffer[13];

g_uiTimeColdWaterInitial = U2RXBuffer[14];

g_uiTimeColdWaterInitial <<= 8;

g_uiTimeColdWaterInitial |= U2RXBuffer[15];

g_uiTimeHotWaterInitial = U2RXBuffer[16];

g_uiTimeHotWaterInitial <<= 8;

g_uiTimeHotWaterInitial |= U2RXBuffer[17];

g_uiTimeColdWaterFinal = U2RXBuffer[18];

g_uiTimeColdWaterFinal <<= 8;

g_uiTimeColdWaterFinal |= U2RXBuffer[19];

g_uiMixingTimeInitial = U2RXBuffer[20];

g_uiMixingTimeInitial <<= 8;

g_uiMixingTimeInitial |= U2RXBuffer[21];

g_uiMixingTimeFinal = U2RXBuffer[22];

g_uiMixingTimeFinal <<= 8;

g_uiMixingTimeFinal |= U2RXBuffer[23];

g_uiImpFlowmeterCalc1 = U2RXBuffer[24];

g_uiImpFlowmeterCalc1 <<= 8;

g_uiImpFlowmeterCalc1 |= U2RXBuffer[25];

U2RXBuffer[1] = 0x01;

SendPacket(U2RXBuffer, 2);

g_MilkProcessingFlag = 1;

g_uiTaskProcessingStep = 1;

break;

case 0x50:

if (U2RXBuffer[2]) {

g_RFIDTagFlag = 1;

} else {

// g_RFIDTagFlag = 0;

}

uiTemp = g_uiTmr2;

uiTemp &= 0x00FF;

U2RXBuffer[1] = (unsigned char) uiTemp;

uiTemp = g_uiTmr2;

uiTemp >>= 8;

U2RXBuffer[2] = (unsigned char) uiTemp;

SendPacket(U2RXBuffer, 3);

break;

case 0x60: // Liquid Flowmeter Calibration

switch (U2RXBuffer[1]) {

case 0x00: // stop command

uiTemp = g_uiFlowmeterCounter;

uiTemp &= 0x00FF;

U2RXBuffer[1] = (unsigned char) uiTemp;

uiTemp = g_uiFlowmeterCounter;

uiTemp >>= 8;

U2RXBuffer[2] = (unsigned char) uiTemp;

break;

case 0x01: // start command

g_uiFlowmeterCounter = 0;

break;

case 0x02: //

uiTemp = g_uiImpFlowmeterTransf1;

uiTemp &= 0x00FF;

U2RXBuffer[1] = (unsigned char) uiTemp;

uiTemp = g_uiImpFlowmeterTransf1;

uiTemp >>= 8;

U2RXBuffer[2] = (unsigned char) uiTemp;

break;

case 0x03: //

uiTemp = g_uiImpFlowmeterFeed1;

uiTemp &= 0x00FF;

U2RXBuffer[1] = (unsigned char) uiTemp;

uiTemp = g_uiImpFlowmeterFeed1;

uiTemp >>= 8;

U2RXBuffer[2] = (unsigned char) uiTemp;

break;

}

SendPacket(U2RXBuffer, 3);

break;

case 0x65: // Liquid Flowmeter Calibration and read temperatures

g_uiTimeReadingTempsFinal = U2RXBuffer[1];

g_uiTimeReadingTempsFinal *= 10;

g_uiTimeWaterCalibrateFinal = U2RXBuffer[2];

g_uiTimeWaterCalibrateFinal *= 10;

g_uiTimeReadingTempsInitial = g_uiTimeReadingTempsFinal / 2;

g_uiTimeWaterCalibrateInitial = g_uiTimeWaterCalibrateFinal / 2;

g_uiTaskProcessingStep = 0x60;

SendPacket(U2RXBuffer, 3);

break;

case 0xF0: // shutdown

STOP_FEEDWATERPUMP

STOP_TRANSFERPUMP

STOP_MIXERMOTOR

STOP_POWDERMILKMOTOR1

STOP_POWDERMILKMOTOR2

STOP_DOSINGPUMP1

STOP_DOSINGPUMP2

STOP_DOSINGPUMP3

STOP_BOILER

CLOSE_CALFTRAPACCESS

CLOSE_EV1

CLOSE_EV2

CLOSE_EV3

CLOSE_EV4

CLOSE_EV5

CLOSE_EV6

CLOSE_EV7

g_uiTaskProcessingStep = 0;

break;

} //end switch

}

/*–––––––––––––––––––––––

Function Name: _CNInterrupt

Description: CN Interrupt Handler – triggered by the Liquid Flowmeter signal

Inputs: None

Returns: None

––––––––––––––––––––––––*/

void __attribute__((__interrupt__)) _CNInterrupt(void)

{

// g_uiFlowmeterCounter++;

__builtin_btg((unsigned int *)&LATE, 5);

/* reset CN interrupt flag */

IFS0bits.CNIF = 0;

}

/*–––––––––––––––––––––––

Function Name: _INT0Interrupt

Description: INT0 Interrupt Handler – triggered by the Liquid Flowmeter signal

Inputs: None

Returns: None

––––––––––––––––––––––––*/

void __attribute__((__interrupt__)) _INT0Interrupt(void)

{

g_uiFlowmeterCounter++;

// __builtin_btg((unsigned int *)&LATE, 5);

/* reset INT0 interrupt flag */

IFS0bits.INT0IF = 0;

}

/*–––––––––––––––––––––––

Function Name: _T2Interrupt

Description: Timer2 Interrupt Handler

Inputs: None

Returns: None

––––––––––––––––––––––––*/

void __attribute__((__interrupt__)) _T2Interrupt( void )

{

g_RFID_DataCntr = 0;

TMR2 = 0;

IFS0bits.T2IF = 0;

}

/*–––––––––––––––––––––––

Function Name: _T3Interrupt

Description: Timer3 Interrupt Handler – 100ms

Inputs: None

Returns: None

––––––––––––––––––––––––*/

void __attribute__((__interrupt__)) _T3Interrupt( void )

{

switch (g_uiTaskProcessingStep) {

case 0x00:

g_ui100msCounter1 = 0;

g_uiStateFeederMachine = STATEMACHINE_READY;

STOP_FEEDWATERPUMP

CLOSE_EV3

CLOSE_CALFTRAPACCESS

break;

case 0x01:

if (g_ui100msCounter1++ == 10) { // wait 1s and start feeder pump

START_FEEDWATERPUMP

OPEN_EV3

OPEN_CALFTRAPACCESS

g_uiStateFeederMachine = STATEMACHINE_PROCESSING;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x02:

if (g_ui100msCounter1++ == 20) { // wait 2s for stabilizing

if (g_RFIDTagFlag) {

OPEN_EV1 // open EV1

g_uiTaskProcessingStep++;

} else {

g_uiTaskProcessingStep = 0;

}

g_ui100msCounter1 = 0;

}

break;

case 0x03:

if (g_ui100msCounter1++ == g_uiTimeHotWaterInitial) { //

OPEN_EV2

CLOSE_EV1

START_MIXERMOTOR

if (g_uiTimePowder1)

START_POWDERMILKMOTOR1

if (g_uiTimePowder2)

START_POWDERMILKMOTOR2

g_uiCounterSubStep = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x04:

if (g_ui100msCounter1 == g_uiTimeColdWaterInitial) { //

CLOSE_EV2

CLOSE_EV3

STOP_FEEDWATERPUMP

g_uiCounterSubStep++;

}

if (g_ui100msCounter1 == g_uiTimePowder1) {

STOP_POWDERMILKMOTOR1

g_uiCounterSubStep++;

}

if (g_ui100msCounter1 == g_uiTimePowder2) {

STOP_POWDERMILKMOTOR2

g_uiCounterSubStep++;

}

g_ui100msCounter1++;

if (g_uiCounterSubStep == 3) {

if (g_uiTimeDosingPump1)

START_DOSINGPUMP1

if (g_uiTimeDosingPump2)

START_DOSINGPUMP2

if (g_uiTimeDosingPump3)

START_DOSINGPUMP3

g_uiCounterSubStep = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x05:

if (g_ui100msCounter1 == g_uiTimeDosingPump1) {

STOP_DOSINGPUMP1

g_uiCounterSubStep++;

}

if (g_ui100msCounter1 == g_uiTimeDosingPump2) {

STOP_DOSINGPUMP2

g_uiCounterSubStep++;

}

if (g_ui100msCounter1 == g_uiTimeDosingPump3) {

STOP_DOSINGPUMP3

g_uiCounterSubStep++;

}

g_ui100msCounter1++;

if (g_uiCounterSubStep == 3) {

g_uiCounterSubStep = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x06:

if (g_ui100msCounter1++ == g_uiMixingTimeInitial) {

START_FEEDWATERPUMP

OPEN_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x07:

if (g_ui100msCounter1++ == 10) { // wait 1s for pressure buildup

OPEN_EV2

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x08:

if (g_ui100msCounter1++ == g_uiTimeColdWaterFinal) {

CLOSE_EV2

CLOSE_EV3

STOP_FEEDWATERPUMP

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x09:

if (g_ui100msCounter1++ == g_uiMixingTimeFinal) {

STOP_MIXERMOTOR

OPEN_EV4

START_TRANSFERPUMP

g_uiFlowmeterCounter = 0;

g_uiImpFlowmeterTransf1 = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x0A:

g_uiImpFlowmeterTransf1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_TRANSFERPUMP) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIMEOUT_TRANSFERPUMP)

{

CLOSE_EV4

STOP_TRANSFERPUMP

g_uiImpFlowmeterFeed1 = 0;

g_uiFlowmeterCounter = 0;

OPEN_EV5

g_uiStateFeederMachine = STATEMACHINE_FEEDING;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x0B:

g_uiImpFlowmeterFeed1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_FEEDING) {

if (((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 &&

g_uiImpFlowmeterFeed1 >= g_uiImpFlowmeterTransf1) ||

g_ui100msCounter1 == TIMEOUT_FEEDING)

{

CLOSE_EV5

CLOSE_CALFTRAPACCESS

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x0C:

if (g_ui100msCounter1++ == 10) { // wait 1s

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep = 0x30;

}

break;

case 0x30:

g_uiStateFeederMachine = STATEMACHINE_CLEANING;

START_FEEDWATERPUMP

OPEN_EV1

OPEN_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

case 0x31:

if (g_ui100msCounter1++ == g_uiTimeHotWaterCleaning1) {

STOP_FEEDWATERPUMP

CLOSE_EV1

CLOSE_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x32:

if (g_ui100msCounter1++ == g_uiTimeReadWaterTemp) {

OPEN_EV4

OPEN_EV5

START_TRANSFERPUMP

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x33:

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_TRANSFERPUMP) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIMEOUT_TRANSFERPUMP)

{

CLOSE_EV4

STOP_TRANSFERPUMP

CLOSE_EV5

OPEN_EV6

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x34:

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_EVACUATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIMEOUT_EVACUATE)

{

START_FEEDWATERPUMP

OPEN_EV1

OPEN_EV7

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x35:

if (g_ui100msCounter1++ == g_uiTimeHotWaterCleaning2) {

CLOSE_EV1

CLOSE_EV7

OPEN_EV2

OPEN_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x36:

if (g_ui100msCounter1++ == g_uiTimeColdWaterCleaning1) {

STOP_FEEDWATERPUMP

CLOSE_EV2

CLOSE_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x37:

if (g_ui100msCounter1++ >= g_uiTimeEvacWaterCleaning2 && g_ui100msCounter1++ >= g_uiTimeReadWaterTemp) {

OPEN_EV4

OPEN_EV5

CLOSE_EV6

START_TRANSFERPUMP

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x38:

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_TRANSFERPUMP) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIMEOUT_TRANSFERPUMP)

{

STOP_TRANSFERPUMP

CLOSE_EV4

CLOSE_EV5

OPEN_EV6

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x39:

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_EVACUATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIMEOUT_EVACUATE)

{

START_FEEDWATERPUMP

OPEN_EV2

OPEN_EV7

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x3A:

if (g_ui100msCounter1++ == g_uiTimeColdWaterCleaning2) {

STOP_FEEDWATERPUMP

CLOSE_EV2

CLOSE_EV7

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x3B:

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_EVACUATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIMEOUT_EVACUATE)

{

CLOSE_EV6

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x3C:

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep = 0;

break;

case 0x3D:

break;

case 0x3E:

break;

case 0x60:

g_uiStateFeederMachine = STATEMACHINE_CALIBRATE;

START_FEEDWATERPUMP

OPEN_EV2

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

case 0x61:

if (g_ui100msCounter1++ == 10) {

OPEN_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x62:

if (g_ui100msCounter1++ == g_uiTimeWaterCalibrateInitial) {

STOP_FEEDWATERPUMP

CLOSE_EV2

CLOSE_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x63:

if (g_ui100msCounter1++ == g_uiTimeReadingTempsInitial) {

OPEN_EV4

START_TRANSFERPUMP

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x64:

g_uiImpFlowmeterTransf1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_TRANSFERPUMP_CALIBRATE)

{

STOP_TRANSFERPUMP

CLOSE_EV4

START_FEEDWATERPUMP

OPEN_EV2

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x65:

if (g_ui100msCounter1++ == 10) {

OPEN_EV3

OPEN_EV6

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x66:

case 0x67:

g_uiImpFlowmeterFeed1 = g_uiFlowmeterCounter;

if (g_ui100msCounter1 == g_uiTimeWaterCalibrateFinal) {

STOP_FEEDWATERPUMP

CLOSE_EV2

CLOSE_EV3

g_uiTaskProcessingStep++;

}

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_EVACUATE_CALIBRATE)

{

CLOSE_EV6

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x68:

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

case 0x69:

if (g_ui100msCounter1++ == g_uiTimeReadingTempsFinal) {

OPEN_EV4

START_TRANSFERPUMP

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x6A:

g_uiImpFlowmeterTransf1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_TRANSFERPUMP_CALIBRATE)

{

STOP_TRANSFERPUMP

CLOSE_EV4

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x6B:

if (g_ui100msCounter1++ == 1) {

OPEN_EV6

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x6C:

g_uiImpFlowmeterFeed1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_EVACUATE_CALIBRATE)

{

CLOSE_EV6

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x6D:

if (g_ui100msCounter1++ == 10) {

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep = 0x70;

}

break;

case 0x70:

START_FEEDWATERPUMP

OPEN_EV1

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

case 0x71:

if (g_ui100msCounter1++ == 10) {

OPEN_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x72:

if (g_ui100msCounter1++ == g_uiTimeWaterCalibrateInitial) {

STOP_FEEDWATERPUMP

CLOSE_EV1

CLOSE_EV3

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x73:

if (g_ui100msCounter1++ == g_uiTimeReadingTempsInitial) {

OPEN_EV4

START_TRANSFERPUMP

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x74:

g_uiImpFlowmeterTransf1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_TRANSFERPUMP_CALIBRATE)

{

STOP_TRANSFERPUMP

CLOSE_EV4

START_FEEDWATERPUMP

OPEN_EV1

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x75:

if (g_ui100msCounter1++ == 10) {

OPEN_EV3

OPEN_EV6

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x76:

case 0x77:

g_uiImpFlowmeterFeed1 = g_uiFlowmeterCounter;

if (g_ui100msCounter1 == g_uiTimeWaterCalibrateFinal) {

STOP_FEEDWATERPUMP

CLOSE_EV1

CLOSE_EV3

g_uiTaskProcessingStep++;

}

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_EVACUATE_CALIBRATE)

{

CLOSE_EV6

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x78:

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

break;

case 0x79:

if (g_ui100msCounter1++ == g_uiTimeReadingTempsFinal) {

OPEN_EV4

START_TRANSFERPUMP

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x7A:

g_uiImpFlowmeterTransf1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_TRANSFERPUMP_CALIBRATE)

{

STOP_TRANSFERPUMP

CLOSE_EV4

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x7B:

if (g_ui100msCounter1++ == 1) {

OPEN_EV6

g_uiFlowmeterCounter = 0;

g_ui100msCounter0 = 0;

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

break;

case 0x7C:

g_uiImpFlowmeterFeed1 = g_uiFlowmeterCounter;

if (g_ui100msCounter0++ == TIME_READING_FLOWMETER_CALIBRATE) {

if ((g_uiFlowmeterCounter – g_uiFlowmeterCounterOld) == 0 ||

g_ui100msCounter1 == TIME_EVACUATE_CALIBRATE)

{

CLOSE_EV6

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep++;

}

g_uiFlowmeterCounterOld = g_uiFlowmeterCounter;

g_ui100msCounter0 = 0;

}

g_ui100msCounter1++;

break;

case 0x7D:

if (g_ui100msCounter1++ == 10) {

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep = 0;

}

break;

case 0xF0: // diagnose – relay control

if (++g_ui100msCounter1 >= g_uiDiagOpenRelayDuration) {

switch (g_ucDiagRelayNumber) {

case 0x01:

LATBbits.LATB0 = 0;

break;

case 0x02:

LATBbits.LATB1 = 0;

break;

case 0x03:

LATBbits.LATB2 = 0;

break;

case 0x04:

LATBbits.LATB3 = 0;

break;

case 0x05:

LATBbits.LATB4 = 0;

break;

case 0x06:

LATBbits.LATB8 = 0;

break;

case 0x07:

LATBbits.LATB6 = 0;

break;

case 0x08:

LATDbits.LATD3 = 0;

break;

case 0x09:

LATCbits.LATC13 = 0;

break;

case 0x0A:

LATCbits.LATC14 = 0;

break;

case 0x0B:

LATEbits.LATE3 = 0;

break;

case 0x0C:

LATEbits.LATE5 = 0;

break;

case 0x0D:

LATEbits.LATE0 = 0;

break;

case 0x0E:

LATEbits.LATE1 = 0;

break;

case 0x0F:

LATEbits.LATE2 = 0;

break;

case 0x10:

LATFbits.LATF0 = 0;

break;

case 0x11:

LATEbits.LATE4 = 0;

break;

case 0x12:

LATFbits.LATF1 = 0;

break;

}

g_ui100msCounter1 = 0;

g_uiTaskProcessingStep = 0;

}

break;

case 0xF1: // diagnose –

// wait

break;

}

IFS0bits.T3IF = 0;

}

/*–––––––––––––––––––––––

Function Name: _INT1Interrupt

Description: INT1 Interrupt Handler – triggered by the RDY/CLK signal

Inputs: None

Returns: None

––––––––––––––––––––––––*/

//void __attribute__((__interrupt__)) _INT1Interrupt(void)

void int1(void)

{

char cDemodOut;

cDemodOut = PORTFbits.RF6;

// LATAbits.LATA7 = cDemodOut;

int i;

T2CONbits.TON = 0;

g_uiTmr2 = TMR2;

TMR2 = 0;

T2CONbits.TON = 1;

if (g_RFID_DataCntr == 0) {

// g_RFID_DataCaptureTemp[0] = 1;

g_RFID_DataCntr++;

} else if (g_RFID_DataCntr < 8) {

if (g_uiTmr2 > 6825 && g_uiTmr2 < 10240) { // (150kHz(6.66us)*64)/0.0625us ; (100kHz(10us)*64)/0.0625us

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

g_RFID_DataCntr++;

} else {

g_RFID_DataCntr = 0;

}

} else if (g_RFID_DataCntr <= 64) {

if (g_uiTmr2 > 6825 && g_uiTmr2 <= 10240) { // (150kHz(6.66us)*2*32clk)/0.0625us ; (100kHz(10us)*2*32clk)/0.0625us

if (g_RFID_DataCaptureTemp[g_RFID_DataCntr-1] == 1)

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

else

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

g_RFID_DataCntr++;

} else if (g_uiTmr2 > 10240 && g_uiTmr2 <= 13600) { // (150kHz(6.66us)*3*32clk)/0.0625us ; (100kHz(10us)*3*32clk)/0.0625us

if (g_RFID_DataCaptureTemp[g_RFID_DataCntr-1] == 1)

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

else {

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

g_RFID_DataCntr++;

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

}

g_RFID_DataCntr++;

} else if (g_uiTmr2 > 13600 && g_uiTmr2 < 20480) { // (150kHz(6.66us)*3*32clk)/0.0625us ; (100kHz(10us)*3*32clk)/0.0625us

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

g_RFID_DataCntr++;

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

g_RFID_DataCntr++;

} else {

g_RFID_DataCntr = 0;

}

} else {

for (i = 0; i < 64; i++) {

g_RFID_DataCapture[i] = g_RFID_DataCaptureTemp[i];

g_RFID_CaptureCompletedFlag = 1;

}

g_RFID_DataCntr = 0;

}

/* reset INT1 interrupt flag */

IFS1bits.INT1IF = 0;

}

/*–––––––––––––––––––––––

Function Name: _INT1Interrupt

Description: INT1 Interrupt Handler – triggered by the DEMOD_OUT signal

Inputs: None

Returns: None

––––––––––––––––––––––––*/

void __attribute__((__interrupt__)) _INT1Interrupt(void)

{

unsigned short i, j, k, m, sumLine, sumCol[4] = {0,0,0,0};

T2CONbits.TON = 0;

g_uiTmr2 = TMR2;

TMR2 = 0;

T2CONbits.TON = 1;

if (g_RFID_DataCntr == 0) {

g_RFID_DataCaptureTemp[0] = 1;

g_RFID_DataCntr++;

} else if (g_RFID_DataCntr < 8) {

if (g_uiTmr2 > 6825 && g_uiTmr2 < 10240) { // (150kHz(6.66us)*64)/0.0625us ; (100kHz(10us)*64)/0.0625us

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

g_RFID_DataCntr++;

if (g_RFID_DataCntr == 8)

g_uiRFID_Fres = g_uiTmr2;

} else {

g_RFID_DataCntr = 0;

}

} else if (g_RFID_DataCntr < 64) {

if (g_uiTmr2 > 6825 && g_uiTmr2 <= 10240) { // (150kHz(6.66us)*2*32clk)/0.0625us ; (100kHz(10us)*2*32clk)/0.0625us

if (g_RFID_DataCaptureTemp[g_RFID_DataCntr-1] == 1)

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

else

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

g_RFID_DataCntr++;

} else if (g_uiTmr2 > 10240 && g_uiTmr2 <= 13600) { // (150kHz(6.66us)*3*32clk)/0.0625us ; (100kHz(10us)*3*32clk)/0.0625us

if (g_RFID_DataCaptureTemp[g_RFID_DataCntr-1] == 1)

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

else {

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

g_RFID_DataCntr++;

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

}

g_RFID_DataCntr++;

} else if (g_uiTmr2 > 13600 && g_uiTmr2 < 20480) { // (150kHz(6.66us)*3*32clk)/0.0625us ; (100kHz(10us)*3*32clk)/0.0625us

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 0;

g_RFID_DataCntr++;

g_RFID_DataCaptureTemp[g_RFID_DataCntr] = 1;

g_RFID_DataCntr++;

} else {

g_RFID_DataCntr = 0;

}

} else {

sumLine = 0;

j = 0;

k = 1;

m = 1;

for (i = 0; i < 5; i++)

g_RFID_DataCapture[i] = 0;

for (i = 8; i <= 57; i++) {

sumCol[k-1] += g_RFID_DataCaptureTemp[i];

if (k++%5 == 0) {

if (sumLine%2 == g_RFID_DataCaptureTemp[i]) {

sumLine = 0;

k = 1;

} else

break;

} else {

sumLine += g_RFID_DataCaptureTemp[i];

// g_RFID_DataCapture[j] = g_RFID_DataCaptureTemp[i];

// j++;

g_RFID_DataCapture[j] <<= 1;

g_RFID_DataCapture[j] |= g_RFID_DataCaptureTemp[i];

if (m++%8 == 0) {

m = 1;

j++;

}

}

}

if (i == 58 && sumCol[0]%2 == g_RFID_DataCaptureTemp[58] && sumCol[1]%2 == g_RFID_DataCaptureTemp[59] &&

sumCol[2]%2 == g_RFID_DataCaptureTemp[60] && sumCol[3]%2 == g_RFID_DataCaptureTemp[61] &&

g_RFID_DataCaptureTemp[62] == 0) {

g_RFID_CaptureCompletedFlag = 1;

IEC1bits.INT1IE = 0; // Disable interrupt RFID DEMOD_OUT

}

g_RFID_DataCntr = 0;

}

/* reset INT1 interrupt flag */

IFS1bits.INT1IF = 0;

}

BIBLIOGRAFIE

Anderson NG. 2012. Modifications to an automated calf feeder permit simultaneous suckling. Ceptor Animal Health News. 20(2):13-14

Anderson NG. 2011. Practical Aspects of Accelerated Feeding of Dairy Calves. AABP Proceedings 44:88-100.

Davis Rincker LE, MJ VandeHaar, CA Wolf, JS Liesman, LT Chapin, MS Weber Nielsen. 2011. Effect of intensified feeding of heifer calves on growth, pubertal age, calving age, milk yield, and economics. J. Dairy Sci. 94:3554-3567.

De Paula Vieira A, V Guesdon, AM de Passille, MAG von Keyserlingk, DM Weary. 2008. Behavioural indicators of hunger in dairy calves. Appl. Anim. Behav. Sci. 109:180-9.

Ilie Stoian, Cristina Gavrilut, Maria demetriad – Diete ale viteilor neintarcati, februarie 2013, http://www.meat-milk.ro/diete-ale-viteilor-neintarcati

Jim Paulson – ”Automatic calf feeding systems for pre-weaned dairy calves”,  Dairy Star, July 2009, University of Minesota

http://www.extension.umn.edu/agriculture/dairy/facilities/automatic-calf-feeding-systems/

Khan MA, DM Weary, MAG von Keyserlingk. 2011. Hay intake improves performance and rumen development of calves fed higher quantities of milk. J. Dairy Sci. 94:3547-3553.

Todd C, T DeVries, K Leslie, J Sargeant, and N Anderson, S Millman. 2011. Free-access feeding of acidified milk replacer: effects on calf growth, health and welfare. Proceedings 2011 Research Symposium, University of Guelph.

http://calfcare.ca/calf-care-corner/the-pros-and-cons-of-automated-calf-feeding/, 2015, publicat de Veal Farmers of Ontario, Canada.

https://www.lely.com/the-barn/feeding/ , 2015 brochure, www.lely.com

http://ww1.microchip.com/downloads/en/devicedoc/c30_users_guide_51284f.pdf

http://www.microchip.com/wwwproducts/en/dsPIC30F4011

http://www.cprogramming.com/tutorial/c-tutorial.html

Similar Posts