Gruppe 1 (I1)

1. semester, efteråret 2002

 

COSS

COmputer Styret Saftblander

 

Implementering

 

 

 

 

 

Gruppen:

                                                Allan H. Michaelsen              01119

                                                Christian Z. Nielsen              01113

                                                Jacob Germundsen              01011

                                                Søren S. Munk                       02847

                                                Tonny Mønster                       01021

 

            Vejleder:                     Poul Zanchetta


 







Rev

Dato

Bemærkninger

Side

Afsnit

01

17/12/2002

Implementering skrevet

 

 

 

 

 

 

 

Indholdsfortegnelse

 

Indholdsfortegnelse. 1

Digitaldelen til projekt COSS.. 2

Generel kredsløbsbeskrivelse. 2

Programmering af PEEL’en (ABEL) 4

Analogdelen til Projekt COSS.. 8

Temperatur kredsløb. 8

Temperatur beregninger 10

Væskestandsberegninger 12

Software C++. 17

incl.hpp: 17

def.hpp: 19

main.cpp: 22

Ad512drv.cpp: 23

Bilag 1- Illustrationer for væskestandsberegninger 28

Billede 1. 28

Målte tider for aftapning. 28

Bilag 2 – Stikforbindelser til/fra COSS’en. 30

Bilag 3 – Rutediagrammer for progamkoden. 31

 


Digitaldelen til projekt COSS

Generel kredsløbsbeskrivelse

 

Skrevet af: Jacob Germundsen og Søren Munk.

 

Efter de første par projektmøder, stod det rimeligt klart, hvordan de stillede opg­a­ver skulle deles i mindre delopgaver (se evt. krav­spe­ci­fi­kationen). Op­split­ningen til mindre delkredsløb øger over­skue­ligheden og letter udviklingen af disse.

 

Til pc’en hører et perifært kort kendt som AD512 fra Humusoft. Dette kort udmærker sig ved at være nemt at kommunikere med (pc), rimeligt nøjagtigt og være udstyret med tilpas mange AD og D indgange og DA og D udgange.

 

Humusoft kortet har dog nogle port begrænsninger, da der kun er 2 DA- og 8 digitale udgange. Vi valgte at holde digitaldelen og analogdelen hver for sig.

 

Med 8 digitale udgange, ville der mangle udgange til alle lys­di­o­der. Først havde vi en 3 til 8 dekoder i tankerne (3 til 8 for at kunne slukke dioderne). 4 af lysdioderne lyser nemlig aldrig samtidigt (Pos. Start, Pos. Dos, Frem og Tilbage) og yderligere ville vi også kunne slukke for disse. Da vi så blev bekendt med PEEL 22CV10, overtog den jobbet. PEEL’en indeholder som bekendt et rimeligt array af gates, så den kunne også varetage oscillatordelen til dens egen clock og genereringen af Gray-koden til step­mot­or­styringen.

 

Idéen var jo at have det hele i en kreds. Det endte så med at blive til to kredse, da der skulle sættes en buffer (74HC08) imellem Humusoft kortet og Vand/Saft i Softdrink Automaten (SA). Vi kunne også godt have brugt DA1 udgangen + en for­mod­stand til at styre Væs­ke Varm (LED) med. Dermed havde 2 til 4 dekodningen været overflødig.

 

Oplægget til oscillator kredsløbet, var en simpel 2xNAND oscillator. Den virker ved at Inverter nr. 1 skiftevis oplader og aflader C1 via modstand R1 til tiden Tau. Inverter nr. 2 er med til at skærpe flankerne på firkant pulsen.

Den startede med at være lidt for simpel, men et godt udgangspunkt der har givet årsag til mange hovedbrud igennem udviklingsfasen af elektronikken.

 

Her ses første udkast til oscillatoren.

 

Modstands- og konden­sator værdierne er forvalgt efter følgende formel (og tilpasset ved ændringer til frekvensen passede):

 

Billede 1: Dette princip er udmærket, men fjerner ikke den clamb­ing effekt der sker, når Inverter nr. 2 går høj og dermed et kort øjeblik får 10V til at stå på Inverter nr. 1’s indgang. Denne transient vandrer desværre igennem inverteren og ud på clock’en.

 

Det kan PEEL’en ikke lide på sin CLOCK indgang, så noget måtte gøres. National Semiconductors Applications Notes, gav os den nødvendige viden om det korrekte udseende for dette kredsløb og med en spole på 1mH i serie med clock’en og en ekstra tilpasningsmodstand R2, fik vi pæne firkanter UDEN transienter og det resulterer i at motoren kører jævnt og lydløst.

 

Sådan her er det endelige oscillator kredsløb blevet realiseret:

 

 

Billede 2

 

Der er rimelig stor tolerance på kondensatorer og det endte med et valg på 47nF og en modstandsstørrelse på 50K (R1). R2’s størrelse er ikke vigtig, da den skal bruges til at tilpasse spændingen, så clambing effekten undgås. Den skal bare være større end R1.

L1 er valgt til 1mH, da en oscillator frekvens på ca 200Hz ønskes. Spolen fjerner en evt. sidste rest af transienter.

 

Som clock frekvens vil alt under 230Hz virke, da motoren ikke kan lide området over 220-230Hz!!.

 

Det med at bruge PEEL kredsens gates til oscillator, skal man lade være med. Det har som tidligere nævnt givet mange problemer og den burde have været bygget op omkring sin egen NAND kreds (74HC00) eller en inverter (74HC04) med Schmitt-trigger. Dette kan ydeligere begrundes med, at der står skrevet at nandkredsen skal være af HC-typen.

Dette skal man sikre sig at den valgte PEEL opfylder.

 

Programmering af PEEL’en (ABEL)

Skrevet af: Jacob Germundsen og Søren Munk.

 

 I PEEL’en er der mulighed for at have fra 10 - 22 indgange og dermed fra 10 – 0 udgange. Vi har brugt 8 indgange og alle 10 udgange. PEEL’en genererer 2-bit Gray-kode efter følgende state diagram (se billede 3)

Billede 3

State diagram for graykode generator.

 

 

 

 Der er 4 tilstande i state diagrammet. Derfor skal der som minimum bruges 2 D flip-flops (Q1,Q2). Tilstandene er navngivet alt efter om Q1 og Q2 er: s00, s01, s11, s10.

 Vi vil også kunne styre om stepmotorerne kører og i så fald i hvilken retning, det kan gøres med DIR og HOLD. HOLD er aktiv lav, hvilket betyder at i power on holder motoren stille, indtil der kommer et styresignal fra programmet. Hvis DIR er 1 = aktiv kører motoren fremad, og modsat ved 0 kører den tilbage. Se bilag 3 i rapporten for ABEL koden.

 

 2 til 4 dekoder, med enable output erstatter 3-8 dekoderen og yderligere er der implementeret to buffere og to invertere i PEEL’en. PEEL koden er skrevet i Abel og kommenteringen er i parentes:

 

declarations

clock, hold, dir                       PIN 1, 2, 3;

I en 22cv10 kan clocken kun komme på PIN 1.

(hold og dir på PIN 2 og PIN 3 er indgange der bruges til styring af stepmotorerne.)

 

Q1..Q2                                                PIN 23,22 istype 'reg';

(Q1 og Q2 er vores D flip-flops som bruges til generering af graykoden.)

 

ibuf                                          PIN 6;

obuf                                         PIN 19 istype 'com';

(ibuf er indgangen til en buffer hvor obuf er udgangen af bufferen.)

 

iinv1, iinv2                              PIN 4,5;

(iinv1 og iinv2 er indgange til 2 invertere)

 

inv1 , inv2                               PIN 20,21 istype 'com';

(inv1 og inv2 er udgangene fra inverterne.)

 

taend_2dec4                         PIN 8;

ibit1,ibit2,ibit3                        PIN 9,10,11;

obit1,obit2,obit3,obit4,obit5            PIN 18..14 istype 'com';

(Vi bruger en 2-4 decoder til at styre lysdioderne. taend_2dec4 enabler output af 2-4 decoderen.

ibit1 og ibit2 er indgangene til 2-4 decoderen og ibit3 er en buffer til styring af væske varm lysdioden.)

 

obit1 … obit4 er udgangene fra 2-4 decoderen.

(obit5 er udgangen af bufferen der styrer væske varm lysdioden.)

 

QSTATE =[Q1,Q2];

s00 = [0,0];

s01 = [0,1];

s11 = [1,1];

s10 = [1,0];

(Beskriver vores tilstande og koder dem så man direkte kan bruge udgangene af Q1 og Q2)

 

equations   

QSTATE.CLK = clock;

QSTATE.OE  = [1,1];

(Fortæller ABEL at clocken for Q1 og Q2 skal komme på PIN 1, og at output enable altid skal være aktiv.)

 

obit1 = (!ibit2 & !ibit1) & taend_2dec4;

obit2 = (!ibit2 &  ibit1) & taend_2dec4;

obit3 = ( ibit2 & !ibit1) & taend_2dec4;

obit4 = ( ibit2 &  ibit1) & taend_2dec4;

(2-4 decoder    -    Ligningerne for 2-4 decoderen)

 

obit5 = ibit3;

(En buffer  -  vaeske varm)

 

inv1 = !iinv1;

inv2 = !iinv2;

(udgangene af inverterne)

 

obuf = ibuf;

(Bufferen til oscillator delen)

 

state_diagram QSTATE

(tilstandsdiagrammet for Q1,Q2)

 

state s00:" a=0; b=0;

            if dir & hold then s01 else

                        if hold then s10

                                    else s00;

(Tilstand s00 = [0,0].)

 

state s01:" a=0; b=1;

            if dir & hold then s11 else

                        if hold then s00

                                    else s01;

(Tilstand s01 = [0,1].)

 

state s11:" a=1; b=1;

            if dir & hold then s10 else

                        if hold then s01

                                    else s11;

(Tilstand s11 = [1,1].)

 

state s10:" a=1; b=0;

            if dir & hold then s00 else

                        if hold then s11

                                    else s10;

(Tilstand s10 = [1,0].)

 

(Hvis hold er ”1” skal der skiftes til en anden tilstand. Alt efter om dir er ”1” eller ”0” skiftes til den næste henholdsvis forrige tilstand.)

 


Analogdelen til Projekt COSS

 

Temperatur kredsløb

 

Skrevet af: Tonny Mønster.

 

Der henvises til diagrammerne ’Top sheet og Temperature part’ i Bilag 1 i rapporten

 

 For at kunne afgøre væskens temperatur, opbygges et temperaturfølerkredsløb, med en sensor placeret i beholderen med vand. Dette er opbygget således, at der ved en bestemt temperatur på sensoren fremkommer en DC spænding på kredsløbets udgang.

 

 En siliciumdiode af typen 1N4148 bruges til temperaturmåling. Dens egenskab er at spændingen over den varierer med dens temperatur, når der sendes en konstant strøm gennem dioden. Dette sker ved hjælp af en konstantstrømsgenerator.

 Spændingen over dioden er ca. 0,6 V, og diodens spændingskarateristik viser at spændingen over den falder ca 2 mV. pr. °C opvarmning.

 

 Der bruges et kredsløb baseret på en LM358 kreds. En korrigeret offsetspænding, der sørger for at der kommer 0 V ud ved 0 ºC, og en forstærkning der sørger for at der kommer den ønskede spænding ved den højest ønskede målte temperatur. Offsetspændingen laves ved hjælp af en spændingsdeler, og forstærkningen sørger en tilbagekobling for.

 

 Det er efter afprøvninger i praksis, blevet bestemt at kredsløbets forsyningsspænding skal være +/-5 V. Den +/-15 V forsyningsspænding, der som udgangspunkt var fælles for al hardware, viste sig ikke at have en tilfredstillende stabilitet. Når stepmotoren stod i hold, dykkede spændingen som følge af at strømforsyningen ikke kunne levere den nødvendige strøm.


 Humusoftkortet kan separat fra vores hardware levere en ureguleret DC-spænding på +/-12 V, som vi bestemte at regulere ned til +/- 5 V, med en dual spændingsregulering, hvortil vi valgte regulatorer af typen 7805 og 7905 til henholdsvis + og – regulering. Strømstyrken er sat til 1 mA, da dioden ikke må have en egen opvarmning, som en for stor afsat effekt ville medføre.

 

 Spændingen over dioden, falder med cirka 2 mV pr. grad den opvarmes. Dette føres til den negerede indgang på kredsen (U3A). Dermed fås en positiv stigende spænding ved stigende temperatur, og det er et sådant signal, der ønskes leveret til Humusoftkortet.

 

 Der er samlet ca 50 gange forstærkning i de to kredse, så 2 mV svarer til 100 mV. I den første del af temperaturkredsløbet eksisterer en variabel resistor (RV1) til offsetspændingen og en en fast resistor (R6) til forstærkningen på ca 5 gange. Sidstnævnte er valgt, da praktisk erfaring viser at en variabel forstærkning i den første del, gør det besværligt at lave et stabilt offset. I stedet bruges en variabel forstærkning i det andet trin (U3B) ved hjælp af RV2, denne sættes til ca 10 gange forstærkning, som sammen med den foregående 5 gange forstærkning i alt giver den ønskede 50 gange forstærkning.

 

Der er nu skabt et kredsløb, som kan udnytte diodens lineære del af karakteristikken, der kan udtrykkes ved ligningen y = Ax + B, hvor B er kredsløbets offsetspænding, som er sat lig 0, og A er diodens temperaturkoefficient. Når temperaturen er 0 ºC, er spændingen 0 V og når temperaturen er 30 ºC er spændingen 3 V. Der kan måles fra 0 – 35 ºC. Dette betinges af, at operationsforstærkeren bruger 1,5 V til egen drift. Derfor kan kredsløbets udgangsspænding ikke overstige 3,5 V. En temperaturændring på 10 °C svarer til en spændingsændring på 1 V.

 

Det anvendte humusoftkort, der blandt andet skal håndtere signalet fra temperaturkredsløbet, er forsynet med flere AD konvertere, der vha af den eksisterende software kan opsættes til at fungere i fastlagte områder. Vi bruger her en af disse, opsat i området 0-5 V. Konverteren har 12 bits opløsning og kan omsætte indgående spændingsværdier til digitale heltalsværdier, der kan bruges til temperaturberegning.

Det 50 gange forstærkede og undervejs negerede output fra temperaturkredsløbet føres til humusoftkortets AD-konverter, der omsætter spændingen til den digitalværdi, der skal modtages af det styrende program som omregner denne værdi til en ºC temperatur.

 Programmet udskriver så den aktuelle værdi på en skærm. Signalet returneres til hardwaren og bliver gennem en spændingsdeler (R8 og R9) formindsket 10 gange, hvorefter det sendes til displayet på SA’en.

 Denne formindskelse af signalet blev fundet nødvendig, da vi ønsker at udnytte DA-konverterens fulde opløsning på 12 bit på området ±5 V, hvilket medfører steps på:

 

 

 Temperaturdisplayet viser 199,9 ved 1999 mV, dvs. 10 mV svarer til 1 ºC. Vi har altså en opløsning, der er høj nok til at kunne vises på displayet, samtidig med at systemet kan korrigeres for fejlvisninger vha. softwaren. Der kan registreres udsving i temperaturen på ca. 0,25 °C.

Temperatur beregninger

Skrevet af: Jacob Germundsen

Illustration: Christian Z Nielsen

 

 Med en 12 bits opløsning på AD konverteren (ADC) og 5Vpp som max, fås en LSB værdi på ca 1,22mV. Denne værdi omsættes til de heltals værdier, der bruges som input til temperaturen.

 

Temperatur: INPUT fra COSS’en

 

Facts:

 

 

 

omregningsformlen bliver så:

 

ergo

 

0V fra COSS’ens temperaturkredsløb ~  0°C          0(ADC)

2V fra COSS’ens temperaturkredsløb ~ 20°C   1670(ADC)

 

20°C =           x = 49,054

 

        [ °C ]

 

 

 Den fundne og beregnede værdi udskrives på den tilsluttede monitor.

 

 Temperaturdisplayet skal også have den rigtige spænding for at temperaturen kommer til at passe på displayet.

 

 Indgangsspændingen fra COSS’ens analogdel til ADC’en på Humu­soft­kortet, er den samme som udgangsspændingen fra DA konverteren (DAC) til COSS’ens spændingsdeler kredsløb.

 

 Det smarte ved kun at køre den analoge temperatur igennem PC’en og ikke direkte over i millivoltmeteret, er at det giver mulighed for at tilpasse en eventuel offset værdi til millivoltmeteret.

 

 Humusoftkortet er forsynet med 2 stk. DAC’ere, der sættes op via en jumper på printet. Denne står i området -5V til +5V og det korrigeres der så for i programmet.

 

 Havde området på DAC’en været den samme som ADC’en, ville den værdi der skal sættes op på DAC’en, pånær en evt. offset, være den samme der er på ADC’en. Dette er som beskrevet ikke tilfældet, hvilket giver følgende overvejelser:

 

 Som udgangspunkt indsættes en grov offset på MSB og det giver en rest på den samme størrelse. Der er 10Vpp i stedet for 5Vpp og det ændrer LSB størrelsen til ca. 2,44mV. Det korrigeres der hurtigt for ved at tage ADC værdien for indgående temperatur og dividere med 2. (Da LSB nu er blevet dobbelt så store).

 

Temperatur:   OUTPUT til COSS

 

Facts:

 

 

 

Dette giver følgende udtryk:

 

0V DACoffset = 211 = 2048 = Default værdi i offset

 (bliver muligvis korrigeret fra 2040 til 2056)

 

DAC = ADC2/2 + DACoffset 

 

DACtemperatur = ADC2/2 + DACoffset 

 

 

Dette er det endelige udtryk vi sluttede med at bruge i softwaren.


Væskestandsberegninger

 

Skrevet af: Jacob Germundsen

 

 Softdrink Automaten (SA) er forsynet med 2 væskebeholdere. Den ene til saft og den anden til vand. På hver af disse beholdere sidder der en elektrisk Danfoss magnetventil, der styres med en 24VAC. Denne spænding sørger et relæ, tilsluttet en AC forsyning i SA, for at levere.

 

 Der åbnes for saftbeholderen når DIGITAL stikkets pin 19 er høj (5V) og for vand­beholderen når DIGITAL stikkets pin 20 er høj. Tilsvarende lukkes der igen når der ingen spænding er på disse to pins (altså når de er lave).

 

 På hver beholder er der monteret et 10kohm linært dreje potentiometer med en fastspændt arm, der har en flyder i modsatte ende. Denne flyder hviler så at sige på væskens overflade. Det vil sige at den følger med væskestanden op og ned i beholderen. Armens vinkel er lidt under vandret ved væske_max[1] og ændrer sig ca 35 grader mod væske_min (se Bilag 1 Billede 1).

 

 Ideelt set ville en lineær aftastning af væskestandshøjden være det bedste, men det kan godt bruges alligevel, da nøjagtigheden er indenfor de 10 %, som der kræves. Karakteristikken ligner den ene side af en positiv parabel i bundområdet af kurven (Det er i virkeligheden en cirkelbue med et skævt offsat center, dette skal forstås således at potmetret burde sidde midt imellem væske_min og væske_max). Dette område kommer flyderen aldrig helt ned i, så det lykkes at holde aflæsningen indenfor de 10% unøjagtighed vi har opgivet i blandings og mængde tolerancer.

 

 Humusoftkortet er forsynet med 8 stk. AD konvertere, der kan sættes op af softwaren til at fungere i forskellige fastlagte områder. Vi bruger 2 af disse AD’ere opsat af softwaren i området 0-5V.

Med de 12 bits opløsning på konverteren og en reference værdi på 4,096V, fås en LSB værdi på 1 mV. Denne værdi er i sig selv ikke så vigtig, men giver de heltals værdier, der bruges som input til væskestands beregningerne.

 

 For at få ”potentiometerstillingen” ind i pc’en og dermed programmet, sættes en reference spænding på begge potentiometres ender. Dermed kan der udtages en DC spænding på midterbenet der er forbundet til AD konverteren, der varierer alt efter hvor flyderen er i beholderen. (Se Bilag 1 i rapporten - Saft og Vand potentiometre). Kabelsættet er fremstillet således at væske_max giver et større tal end væske_min.

 

 Ved observation af de to potentiometre på beholderene er følgende fastslået:

 

 Disse observationer betragter vi som to rette linier, med hver deres hældnings­koef­ficient , da der max afviges fra hældningstallet med 9 grader (skraveret med gråt på Bilag 1 Billede 1). Ved at gøre dette kan ethvert væske niveau bestemmes i beholderne. Denne procedure bruges i to af funktionerne til programmet.


 


Vandbeholder

 

Kommentarer

Saftbeholder

Mængde (vol):

 

Mængde (vol):

 

y= AD0

x= Liter

 

    

 

 

 

 

 

y: ADC (max værdi)

y1: ADC (min værdi)

x-x1:  4 (liter max og min)

 

 

Liniens ligning med omflyt­tede led sådan som den bruges i programmet:

 

 

y=AD1

x= Liter

 

    

 

 

 

 Tallene i den følgende tabel er de værdier vi har aflæst under hardware og software implementeringen. Disse værdier kan selvfølgelig ændres og vil også blive det ved potmeter skift. Hvis bare potmetrene er lineære, så er deres størrelse ukritisk.

 

Regneeksempel :




 

 

 

 

 

      

 

 

Denne forskel på  er et udtryk for de 2 potentiometres tolerance afvigelse. De er dog forholdsvis ens!!

 

Liniens ligning:   y-y1=(x-x1) flyttet rundt:

 

 

Den endelige ligning med indsatte værdier bliver så:

 

 

 

 

          

 

 

 

 På samme måde foregår det med skænketiden. Alt efter mængden i beholderne ændres tiden for hvor hurtigt en kop fyldes til en bestemt volumen. I dette tilfælde 170mL.

 


 Ved observation af de to beholdere er følgende fastslået:

sekund at tømme disse

 

 Disse observationer betragter vi som en ret linie, med en hældnings­koef­ficient . Ved at gøre dette kan åbning­s­tiderne til dosering, for de to væskebeholdere, bes­tem­­mes individuelt.

 

Skænketid:

              

 

y=Liter             x=tid [sekunder]

 

 y-y1=(x-x1)         y-2= -2,424(x-5,25)         

    

y= -2,424x + 14,7                  

 

 En korrekt skænket kop består af 1 del saft og 5 dele vand, 6 dele i alt. Dermed er det indlysende at beregne en åbningstid for både vand og saft som om at hver af disse skulle fylde en hel kop og så reducere deres åbningstid til 1/6 for saftens vedkommende og 5/6 for vandet. Ved forsøg og følgende væskestands volumen målinger, har det vist sig at udregningerne passer.

 

 Et regneeksempel på hvordan programmet beregner åbningstiderne for hhv. vand og saft, ved et givet antal liter i tankene:


 



Vand:

Kommentarer

Saft:

 

 

 

 

 

 

 

 

 

 

Liter beregningerne indsat i skænketids ligningen bliver så:

 

 

 

 

 


Software C++

 

Skrevet af: Søren Munk

 

 Her forklares programkoden i detaljer. For at se rutediagrammerne for de enkelte funktioner se Bilag 3.

incl.hpp:

 

Formål:

Includerer alle de filer som skal bruges af programmet.

 

Forklaring:

#ifndef COSS_Includes_hpp

#define COSS_Includes_hpp

 

Hvis den ikke er defineret I forvejen skal vi definere ”COSS_Includes_hpp”

 

#include "def.hpp"

Heri defineres funktions prototyper, konstanter og typer. Så kan man nøjes med at indclude en fil for at have ”adgang” til funktion og konstanter.

 

#include "ad512drv.hpp"

Indeholder funktions prototyper for ad512drv.cpp, så vi kan kalde enableAD512, DigitalOutput mm.

 

#include <iostream>

Bruges af cout for at kunne bruge input/output stream

 

#include <iomanip>

Bruges for at kunne lave manipuler med streams, fx setprecision.

 

#include <conio.h>

Bruges for at kunne lave input/output til console vinduet

 

#include <sys/timeb.h>

Bruges for at få den struktur der hedder __timeb64 og funktionen _ftime64() som henter tiden og gemmer den i en __timeb64 struktur.

 

__timeb64 strukturen indeholder:

 

dstflag

            Er forskellig fra 0 hvis vi er i sommerperioden

Millitm

            Antal millisekunder

Time

            Tiden, i sekunder, siden midnat d. 1 January 1970.

Timezone

            Tidsforskydelse i minutter fra UTC og lokaltiden.

 

#include <windows.h>

Skal inkluderes for at få adgang til windows funktionskald

 

#include <process.h>

Giver adgang til funktionen spawn() som bruges til at kalde/starte andre processer.

 

#include <signal.h>

Giver adgang til funktionen signal() som kan bruges til at fortælle windows hvad den skal gøre hvis visse ting sker.

 

using namespace std;

Fortæller sompileren at hvis den ikke kan genkende en funktion skal den prøve med std::funktionsnavn, fx cout = std::cout

 

#endif

Her afsluttes definitionen af COSS_Includes_hpp.

 

 

def.hpp:

 

#ifndef COSS_Styring_hpp

#define COSS_Styring_hpp

 

Definerer COSS_Styring_hpp hvis den ikke er defineret i forvejen.

 

typedef unsigned long DWORD;

Definerer en type (DWORD) som er en 32-bit unsigned int.

DWORD er en windows standard som bruges i forbindelse med windows funktionskald.

 

#define PRIORITY                             HIGH_PRIORITY_CLASS

Prioriteten vores program skal køre med.

 

#define myProg                                 "a:\\Coss.exe"

#define myProg_path                       "\"a:\\Coss.exe\""

Stien til det program som skal kaldes hvis vores program bliver lukket på en unaturlig måde. Her er det selvfølgelig vores eget program der skal køres igen. myProg_path er stien til programmet inkluderet i ” ”.

 

#define CLEAR                                 "                   "

#define HORLINE                             "\xCD"

#define VERLINE                             "\xBA"

#define TOPLEFT                            "\xDA"

#define TOPRIGHT                           "\xBF"

#define BUTTOMLEFT                    "\xC0"

#define BUTTOMRIGHT                  "\xD9"

#define TOPMID                               "\xC2"

#define BUTTOMMID                       "\xC1"

#define XOFFSET                            15

#define YOFFSET                            3

#define CONWIDTH             50

#define CONMID                              25

#define TEXT_COLOR                    FOREGROUND_BLUE | !FOREGROUND_INTENSITY

#define BACK_COLOR                   BACKGROUND_INTENSITY

Konstanter der bruges til at  styre opsætningen i status vinduet.

 

#define POSITION_START 1

#define POSITION_DOS                 0

#define FREM                                   0

#define TILBAGE                              1

#define DAOFFSET                         2045

#define TEMPOFFSET                   0.22

#define TOM_KOP                           1

#define BRUGT_KOP                      0

#define AFDRYP_TID                      2000

Konstanter som bruges i programmet, så det bliver lidt nemmere at læse.

 

#define STEPMOTOR_HOLD_L    1

#define STEPMOTOR_DIR 2

#define VENTIL_SAFT                    4

#define VENTIL_VAND                   8

#define TAEND_2DEC4                 16

#define DECODER_1                     32

#define DECODER_2                     64

#define DECODER_3                     128

Konstanter som bruges til de digitale udgange, så programmet bliver mere letlæseligt, og måske nemmere at forstå.

 

#define START_AKTIV                    1

#define RESET_AKTIV                   2

#define POS_START                       4

#define POS_DOS                           8

#define KopIHolder                           16

Konstanter som bruges til de digitale indgange, så programmet bliver mere letlæseligt.

 

#define VAND                                   0

#define SAFT                                    1

#define TEMP                                   2

Konstanter der beskriver de analoge indgange, så programmet bliver mere letlæseligt.

 

#endif

Her afsluttes definitionen af COSS_Styring_hpp.

 

globaleVar.hpp:

Indeholder de globale variabler vi burger i programmet.

 

int digital_udgang = 0;

Repræsenterer hvad vi har stående på vores digitale udgange. Da man ikke kan læse hvad man har på de digitale udgange må huske det på anden vis.

 

bool resetAktiv = false;

Bruges for at sikre at hvis reset aktiveres vil programmet ikke gøre andet.

 

int asaft = 107;

int avand = 98;

Hældningstal til beregning af vand og saft mængder.

 

int max_vand = 752;

int min_vand = 386;

int max_saft = 2278;

int min_saft = 1794;

Minimum og maksimum værdier der bruges til beregning af vand og saft mængder.

 

ad512drv.hpp:

Indeholder functions prototyper for ad512drv.cpp.

 

main.cpp:

main()

Har til formål at forberede systemet og starte COSS styringen.

 

Forklaring:

#include "incl.hpp"

Indeholder alle de libraries vi skal bruge i programmet, samt funktionsprototyper for at vi kan bruge diverse funktioner.

 

void main() {

main() kaldes som den første funktion, når programmmet starter.

 

clearDisp():

Sletter alt hvad der skulle stå i displayet

 

signal(SIGINT,signalHandler);

signal(SIGABRT,signalHandler);

Funktionen signal() fortæller windows hvad den skal gøre hvis der skulle opstå en af de følgende events:

CTRL+C signal

Abnormal termination

 

Dvs hvis man trykker CTRL+C bliver koden der står i signalHandler() udført, men det er ikke vores program der gør hvad der står i signalhandler(), Windows laver en process som udfører koden.

 

SetPriorityClass(GetCurrentProcess(),PRIORITY)

 

SetPriorityClass()

Sætter prioriteten for en process så den får mere tid på CPU’en.

 


GetCurrentProcess()

Returnerer et handle til vores program som andre funktion kan bruge til at få fat i vores proces. PRIORITY er defineret i koden og kan have en af følgende værdier:

REALTIME_PRIORITY_CLASS

HIGH_PRIORITY_CLASS

ABOVE_NORMAL_PRIORITY_CLASS

NORMAL_PRIORITY_CLASS

BELOW_NORMAL_PRIORITY_CLASS

IDLE_PRIORITY_CLASS

 

Vi har defineret PRIORITY til at være HIGH, dvs man får mere tid på CPU’en end andre programmer/processer.

Som default kører alle programmer med NORMAL prioritet. Vi sætter altså vores program til at køre med HIGH priority.

 

enableAD512()

Gør det muligt at bruge Humusoft AD512 kortet, returnværdien er:

 

-0  hvis alt gik godt.

-1 hvis kortet ikke er installereret eller man ikke har rettigheder til at bruge det som bruger.

-2 hvis driveren ikke kunne enable kortet, kan fx være at det ikke har adressen 0x300.

 

setDigitalOut(TAEND_2DEC4, false);

Deaktiverer alt.

 

 

Ad512drv.cpp:

Giver muligehed for at bruge Humusoft AD512 kortet.

 

enableAD512():

Giver mulighed for at bruge Humusoft kortet.

Her er lavet ændringer så der bliver skrevet relevante fejlbeskeder ud.

 

func.cpp:

Indeholder alle funktioner der skal bruges til styringen af COSS’en.

 

clearDisp():

Funktionen sletter alt der skulle stå på skærmen og sætter tekst- og baggrundsfarven til hvad de nu er sat op til i programmet

 

doser():

Denne funktion tager sig af doseringen af vand og saft, under forudsætning af at alt er ok, dvs. at commonChecks() ikke giver nogen fejl. Hvis der trykkes reset afbrydes doseringen og reset() funktionen kaldes.

 

koerSlaede(short direction):

Funktionen skifter retningen på stepmotoren så den kører i retning direction og starter stepmotoren via PEEL’en.

 

Bool kopStatus(bool gemme, bool status):

Funktionen skal holde styr på om koppen er blevet skiftet.

 

void moveCursorXY(DWORD X, DWORD Y):

Funktionen flytter cursoren til X,Y i konsol vinduet.

 

void printTrueFalse(bool value):

Skal udskrive Ja hvis value er true og Nej hvis den er false. Teksten udskrives i henholdsvis grøn og rød.

 

void printTrueFalse(bool value, float out):

Funktionen gør det samme som printTrueFalse(bool value) men i stedet for at udskrive ja/nej udskrives out.

 

reset():

reset() slukker for vand- og saft- ventilerne, stopper stepmotoren via PEEL’en, venter i AFDRYP_TID sekunder og kører kopholderen tilbage til position start.

 

showStaus():

Udskriver status for COSS’en som vist på billede 1.

 

Billede 1 Status billede uden tilsluttet COSS

 

void signalHandler(int signal):

Fortæller Windows at hvis vores program får et signal signal skal den udføre koden i funktionen.

Funktionen slukker alle vores digitale udgange og starter vores program forfra.

 

Start():

Selve styringen af COSS’en, denne funktion vil aldrig terminere.

start() afventer et start/reset signal, ved start køres kopholderen til position dosering, der doseres og kopholderen køres tilbage til position start, under forudsætning af at alt er ok, dvs de krav der er beskrevet i commonChecks() er ok.

Hvis et af kravene ikke er opfyldt udføres der et reset og der doseres ikke.

 

bool checkPos(int position):

Funktionen checker om kopholderen er i pos_start eller pos_dos, Og tænder for den respektive LED.

 

bool checkKopIHolder():

Funktionen checker om der er en kop i kopholderen.

 

bool commonChecks(int position):

Kontrollerer om følgende krav er opfyldt:

 

Desuden checkes at kopholderen befinder sig i den position funktionen har modtaget.

 

int getAnalogIn(short kanal):

Funktionen læser den analoge spænding på indgang kanal i intervallet 0 V– 5 V.

 

bool getDigitalIn(short kanal, bool value):

Funktionen læser den boolske værdi for indgang kanal og checker om den er lig value.

 

bool getKopHolderPos():

Funktionen udskriver en tekst alt efter hvor kopholderen er. Fx hvis kopholderen er på vej til dosering udskrives teksten:

 

“Start -> Dosering”

 

bool getResetAktiv():

Funktionen returnerer true hvis der trykkes på reset knappen.

 

int getSaftNiveau():

Funktionen returnerer et heltal der repræsenterer den spænding der står på indgangen. 0V giver 0 og 4095 giver ca. 5V.

 

float getSaftVolumen():

Funktionen udregner hvor mange liter væske der er i saft-tanken.

 

bool getStartAktiv():

Funktionen returnerer true hvis der trykkes på start knappen.

 

DWORD getTid():

Udregner tiden i millisekunder siden midnat d. 1 Januar 1970.

 

int getVandNiveau():

Funktionen returnerer et heltal der repræsenterer den spænding der står på indgangen. 0V giver 0 og 4095 giver ca. 5V.

 

float getVandTemp():

Funktionen udregner og returnerer temperaturen i vandet. Hvis væsken er for varm, altså over 16 grader celsius, tændes væske varm LED.

 

float getVandVolumen():

Funktionen udregner hvor mange liter væske der er i saft-tanken.

 

void setDigitalOut(short kanal, bool value):

Funktionen sætter den digitale udgang kanal til value, er den allerede sat til value sker der ikke noget.

 

void setAnalogOut(short kanal, short value):

Funktionen sætter den analoge udgang kanal til value, hvis den ligger inden for det accepterede interval 0-4095, ved 12 bit converter.

 

void setTextColor(DWORD dwAttributes):

Funktionen sætter farven på teksten til dwAttributes, dwAttributes representerer RGB for baggrunden og for tekstfarven.

 


Bilag 1- Illustrationer for væskestandsberegninger

Billede 1

Her er det tydeliggjort, hvordan potentiometrene til væskestanden er placeret og hvilke ulemper det giver.

Målte tider for aftapning

 

Tidligt i arbejdet med COSS foretog vi målinger på tider for vand­gennem­strømning i ventilerne for at sikre os at tiderne var ens.

I tabellen herunder ses måleresultaterne for opfyldning af en 180 mL kop.

 

(Under realiseringen blev vi enige om at 170mL, var en mere rigtig størrelse at fylde koppen med. Pånær den ændrede volume og dermed lidt større åbningstid pr ventil, ændrer det ikke noget)


 

Vand

Måling 1

Måling 2

måling 3

Gennemsnit

Beholder

Liter

Tid i sekunder

Max.

6,0

4,00

3,95

4,00

3,98333333

Midt

4,0

4,75

4,85

4,70

4,76666667

Min.

2,0

6,00

6,01

6,00

6,00333333

Saft

Tid i sekunder

Max.

6,0

4,06

4,06

3,98

4,03333333

Midt

4,0

4,95

4,92

4,75

4,87333333

Min.

2,0

6,12

6,06

6,04

6,07333333

 

Som det fremgår af tabellen opfører vand- og saftbeholdernes ventiler sig ens, og vi kunne derfor betragte de to systemer som identiske når vi senere skulle beregne skænketider.


Bilag 2 – Stikforbindelser til/fra COSS’en


Bilag 3 – Rutediagrammer for progamkoden

 

void main (int, char *[ ])                                                           bool getDigiTalIn (short, bool)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                        void showStatus ()

 

 

 

 

 

 

 

 

 

 

 


       void start ()

bool checkPos (int)

bool checkPos (int)

 

 

 

 


    bool checkKopIHolder ()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

bool getKopHolderPos ()

 

 

 

 

 

 

 

 

 


bool commonChecks (int)
bool doser ()

 


                  int getAnalogIn (short)                                                       DWORD getTid (void)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

         bool stepMotorStyring (int,int)

 

 

 

 

 

 

 

 

 

 

 

               void setTextColor (unsigned long)


void setDigitalOut (short, bool)                                                            int getVandNiveau ()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

void setAnalogOut (short, short)

 

 

  

 

 

 

 

 

 

                             void clearDisp ()

 

 

 

 

 

bool getStartAktiv ()

 

 

 

 

 

 


float getVandTemp ()                                       void moveCursorXY (DWORD, DWORD)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

void koerSlaede (short)                      

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


          void printTrueFalse (bool)                                             float getSaftVolumen ()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    void printTrueFalse (bool, float)

 

                                       

 

int getSaftNiveau ()                 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


            bool getResetAktiv ()                                                     void signalHandler (int)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

bool kopStatus (bool, bool)

 

float getVandVolumen ()         

 

 

 

 

 

 

 

 

 

 

 

 

 


void reset ()

 



[1] Der opereres med termer som vand_min, vand_max osv. Disse størrelser svarer til min_vand, max_vand osv i selve programmet