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
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Figură 2-1 Schema de principiu a instalației 12 [305186] (ID: 305186)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
