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 |
|
|
|
|
|
|
|
|
Programmering af PEEL’en (ABEL)
Bilag 1- Illustrationer for væskestandsberegninger
Bilag 2 – Stikforbindelser til/fra COSS’en
Bilag 3 – Rutediagrammer for progamkoden
Skrevet af: Jacob Germundsen og Søren Munk.
Efter de første par projektmøder, stod det rimeligt klart,
hvordan de stillede opgaver skulle deles i mindre delopgaver (se evt. kravspecifikationen).
Opsplitningen til mindre delkredsløb øger overskueligheden 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 lysdioder.
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 stepmotorstyringen.
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 formodstand til at styre Væske 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 kondensator 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
clambing 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.
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.)
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.
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 2V fra COSS’ens
temperaturkredsløb ~ 20°C 20°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å Humusoftkortet, 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.
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 vandbeholderen
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ældningskoefficient
, 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 omflyttede
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å Liniens ligning: y-y1= 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ældningskoefficient
. Ved at gøre dette kan åbningstiderne til dosering, for de
to væskebeholdere, bestemmes individuelt.
|
Skænketid: |
|
y=Liter x=tid [sekunder] y-y1= 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å: |
|
Skrevet
af: Søren Munk
Her forklares programkoden i detaljer. For at
se rutediagrammerne for de enkelte funktioner se Bilag 3.
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.
#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()
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.
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.

Her er det tydeliggjort, hvordan potentiometrene til
væskestanden er placeret og hvilke ulemper det giver.
Tidligt i arbejdet med COSS foretog vi målinger på tider for
vandgennemstrø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.

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