Gruppe 1 (I1)
1. semester, efteråret 2002
COSS
COmputer Styret Saftblander
Rapport
Gruppen:
Allan H. Michaelsen 01119
Christian
Z. Nielsen 01113
Jacob Germundsen 01011
Søren S. Munk 02847
Tonny Mønster 01021
Vejleder: Poul Zanchetta
Denne rapport beskriver
konstruktionen af en kontrolenhed til en eksisterende saftblander. Enheden skal
virke således at blanderen kan dosere vand og saft i en specificeret mængde med
forholdet 5:1, så længe at vandtemperaturen ikke er over 16 °C. Der er flere
krav til enheden som kan ses i kravspecifikationen.
Kontrolenheden (vi kalder den COSS) består af
flere dele såsom software og hardware, disse igen er delt op i mindre dele og
gjort realiserbare derudfra.
Software: Softwaren er skrevet i C++
for den del der kører på Pc’en og der er brugt ABEL til at programmere en PEEL
som er en integreret del af hardwaren.
Hardware: Hardwaren er delt op i 2 dele,
en analog og en digital. Digitaldelen er bygget op omkring en PEEL og analogdelen
er bygget op omkring en dobbelt operationsforstærker.
Indhold .................................................................................................................. Afsnit..........Side
Der skal udvikles og opbygges en
softdrinkautomat baseret på en allerede eksisterende mekanisk opstilling.
En softdrink fremstilles ved at en
passende mængde saft og vand blandes i en kop på følgende måde:
Ved et tryk på startknappen skal koppen
køre frem til doseringspositionen, hvis
•
der er en kop i
holderen
•
koppen er i
startposition
•
vandets temperatur er
passende lav
•
resetknappen ikke
aktiveres.
Koppen skal stoppe i
doseringsposition og derefter skal dosering af saft og vand påbegyndes.
Når doseringen af saft og vand er
afsluttet, skal koppen køre tilbage til startpositionen.
Krav
Automaten skal i øvrigt overholde
følgende krav:
•
Der skal være
indikering af automatens tilstand og vandets temperatur.
•
Afvigelse af
påfyldningsvolumen må højst være 10 %
•
Dosering skal være i
forholdet 1 del saft til 5 dele vand, med en nøjagtighed på 10 %
•
Dosering må kun ske
når vandets temperatur er 16 °C eller derunder.
•
Omgivelsestemperaturen
er 20 °C.
•
Aktivering af
resetknappen skal stoppe processen og køre kopholderen tilbage til
startposition.
•
Software til
styringen skal bestå af et C++ program
Rapporten er delt op i afsnit som indeholder
punkter såsom resume og konklusion, men også de dokumenter der er gået forud
for rapporten selv:
Vi har i gruppen delt arbejdet ind på følgende
måde:
Rapportfletning
/ Resume / Indledning / Konklusion
·
Allan H Michaelsen
Kravspecifikation
/ Testdokumentation
·
Hele gruppen
Strukturering:
·
Allan H Michaelsen
·
Christian Z Nielsen
Implementering:
·
De enkelte medlemmer af gruppen har været med
til forskellige opgaver. Dette er beskrevet senere i afsnittet implementering.
Selve Projektet kom godt fra start. Vi lavede
kravspecifikationen og struktureringen og fik derudfra konstrueret hardwaren,
det meste af det uden problemer.
Dog skal det nævnes, at de fra kunden leverede
standardopstillinger gav visse problemer, som måtte korrigeres før systemerne
virkede.
Til digitaldelen af hardwaren skulle vi blandt
andet bruge en oscillator til at generere clocksignalet for
stepmotorkontrolleren. Til dette ville vi programmere et kredsløb i vores PEEL,
som skulle generere dette clocksignal. Det gav dog nogle problemer, da vi ikke
kunne få motoren til at køre stabilt med denne opstilling. Som løsning måtte vi
sætte en spole ind for at fjerne det meste af den højfrekvente støj som PEEL’en
havde på udgangen, og derefter kørte det hele som det skulle.
Ligeledes havde vi på analogdelen et lille problem med forsyningsspændingen, som dog blev løst ved at sætte et par spændingsregulatorer ind for at få en stabil forsyning på +/- 5v. Standardopstillingen havde to forstærkertrin, det første med offset og forstærkning og det andet med slutforstærkning, med en signaludgang til displayet imellem de to trin. Men da vi ikke kører direkte til displayet og i stedet lader computeren klare konverteringen af temperatursignalet, kunne vi nu lave fast forstærkning på første trin og gøre det nemmere at lave offsettet.
I en version 2 skulle kalibreringsprocessen gøres nemmere. Vi har faktisk prøvet med en nemmere måde, men det lykkedes desværre ikke at få det præcist nok.
Vi tog gennemsnitsværdierne af de eksisterende min og max værdier for begge potmetre, og udnævnte dem til min og max referencer. Så var ideen at finde en værdi for bunden af hver beholder (når flyderen var i bund), og lægge den midlede min værdi til. Så var det ret nemt at kalibrere da man så bare kunne presse flyderne i bund for at få en kalibreringsværdi.
Vi var ikke tilfredse med den opnåede præcision, da der var for stor spredning på potmetrenes linearitet.
__________________________
Allan H
Michaelsen
__________________________
Christian
Z Nielsen
__________________________
Jacob
Germundsen
__________________________
Søren
S Munk
__________________________
Tonny
Mønster





// Projekt Humusoft
AD 512 kort
//
// Fil AD512DRV.hpp
// Forfatter Erik Gross Jensen
//
// Beskrivelse Header file til funktioner til styring af I/O porte på Humusoft
AD512 Data Acquisition Kort
//
// Version 1.0
201000
//
#ifndef
AD512drv_hpp
#define
AD512drv_hpp
int
enableAD512(void);
unsigned
short AnalogInput(int
ch, int range);
void
AnalogOutput(int ch, int
value);
int
DigitalInput(void);
void
DigitalOutput(int value);
#endif
// Projekt COSS
//
// Fil incl.hpp
//
Forfatter Søren S. Munk
//
#ifndef COSS_Includes_hpp
#define COSS_Includes_hpp
#include "def.hpp"
#include "ad512drv.hpp"
#include <iostream>
#include <iomanip>
#include <conio.h>
#include <sys/timeb.h>
#include <windows.h>
#include <process.h>
#include <signal.h>
#include <string>
using namespace
std;
#endif
//
Projekt COSS
//
// Fil globaleVar.hpp
//
Forfatter Søren S. Munk
//
#ifndef COSS_globalVar_hpp
#define COSS_globalVar_hpp
//Husk
hvad den digitale udgang er
int digital_udgang = 0;
bool resetAktiv =
false;
int
asaft = 107;
int avand =
98;
//Niveau
målere
int
max_vand = 752; //6 liter
int
min_vand = 386; //2 liter
int
max_saft = 2278; //6 liter
int
min_saft = 1794; //2 liter
#endif
// Projekt COSS
//
// Fil def.hpp
//
Forfatter Søren S. Munk
& Jacob Germundsen
//
#ifndef COSS_Styring_hpp
#define COSS_Styring_hpp
////////////////////////////////////
// Type
definitioner !! //
////////////////////////////////////
//0 to
4,294,967,295
typedef unsigned long DWORD;
//////////////////////////////////////
//
Diverse funktioner !! //
//////////////////////////////////////
void clearDisp();
bool doser();
void initialiser(int, char *[]);
void koerSlaede(short);
bool kopStatus(bool,bool);
void
moveCursorXY(DWORD,DWORD);
void printTrueFalse(bool);
void printTrueFalse(bool, float);
void reset();
void showStatus();
void signalHandler(int);
void start();
///////////////////////////////////
// check
functioner !! //
///////////////////////////////////
bool checkPos(int);
bool checkKopIHolder();
bool commonChecks(int);
///////////////////////////////
// get
functioner !! //
///////////////////////////////
int
getAnalogIn(short);
bool getDigitalIn(short,bool);
bool getKopHolderPos();
bool getResetAktiv();
int getSaftNiveau();
float getSaftVolumen();
bool getStartAktiv();
DWORD getTid( void );
int getVandNiveau();
float getVandTemp();
float getVandVolumen();
///////////////////////////////
// set
functioner !! //
//////////////////////////////
void setAnalogOut(short,short);
void setDigitalOut(short,bool);
void setTextColor(unsigned long);
///////////////////////////
//
Konstanter !! //
//////////////////////////
#define PRIORITY HIGH_PRIORITY_CLASS
#define myProg "a:\\Coss.exe"
#define myProg_path "\"a:\\Coss.exe\""
//CONSOLE
DISPLAY
#define CLEAR " "
#define HORLINE "\xCD" //"\xC4"
#define VERLINE "\xBA" //"\xB3"
#define TOPLEFT "\xDA" //"\xDA"
#define TOPRIGHT "\xBF" //"\xBF"
#define BUTTOMLEFT "\xC0" //"\xC0"
#define BUTTOMRIGHT "\xD9" //"\xD9"
#define TOPMID "\xC2" //"\xC2"
#define BUTTOMMID "\xC1" //"\xC1"
#define XOFFSET 15
#define YOFFSET 3
#define STATUS_TEXT_OFFSET 12
#define CONWIDTH 50
#define CONMID 25
#define TEXT_COLOR FOREGROUND_BLUE
| !FOREGROUND_INTENSITY
#define BACK_COLOR BACKGROUND_INTENSITY
#define
FOREGROUND_BLACK FOREGROUND_BLUE &
FOREGROUND_RED & FOREGROUND_GREEN
#define FOREGROUND_YELLOW FOREGROUND_GREEN | FOREGROUND_RED |
FOREGROUND_INTENSITY
//divers
konstanter
#define POSITION_START 1
#define POSITION_DOS 0
#define TOM_KOP 1
#define BRUGT_KOP 0
#define FREM 0
#define TILBAGE 1
#define DAOFFSET 2045 //2022
#define TEMPOFFSET 0.22
#define AFDRYP_TID 2000
//bit på
digital kanal OUT
#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
//bit på
digital kanal IN
#define START_AKTIV 1 //PIN 12
#define RESET_AKTIV 2 //PIN 13
#define POS_START 4 //PIN 14
#define POS_DOS 8 //PIN 15
#define KopIHolder 16 //PIN 16
//Analog
kanaler IN
#define VAND 0 //PIN 1
#define SAFT 1 //PIN 2
#define TEMP 2 //PIN 3
#endif
// Projekt Humusoft AD 512 kort
//
// Fil AD512DRV.cpp
// Forfatter Erik Gross Jensen
//
// Beskrivelse Funktioner til styring af I/O porte på
Humusoft AD512 Data Acquisition Kort
//
// Ændret Søren Munk, Udskriver
fejlbeskeder
//
// Version 2.0 201000
//
#include <conio.h>
#include <windows.h>
#include <stdio.h>
#include <process.h>
#define IOENABLE 0x100
// base address
for the AD512 kort
#define AD512BASE 0x300
#define IOLENGTH 8
/*****************************************************************************
enableAD512
enable direct
access to I/O ports
Input: ingen
Output: 0 =
enable ok,
error otherwise
/****************************************************************************/
int enableAD512(void)
{
OSVERSIONINFO ver;
HANDLE drvhandle;
unsigned long cb;
unsigned message[2];
int ok;
/* Test the Win32 platform
we run on. If this is not Windows NT/2000, we can
just return success because I/O
access is already allowed. */
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&ver);
if (ver.dwPlatformId
!= VER_PLATFORM_WIN32_NT)
return(0);
/* Open the handle to the
DIRECTHW device driver. The driver must be installed for this to succeed.
If this fails the board cannot be accessed. */
drvhandle = CreateFile("\\\\.\\DIRECTHW",
GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
if (drvhandle ==
INVALID_HANDLE_VALUE) {
printf(" FEJL: enableAD512():\tKan
ikke finde DIRECTHW!\n");
printf("\a\n Mulige
grunde:\n\tHumusoft AD512 er ikke installeret eller \
\n\tdu har ikke nok rettigheder som
bruger. \
\n\tFor at installere AD512 find setup.bat
i \
\tt:\\install\\humusoft\\setup\\
\n");
return(-1);
}
/* Send a request to the driver. This consists of the
request code (IOENABLE)
and
two-word message containing I/O address and range to be enabled. */
message[0] = AD512BASE;
message[1] = IOLENGTH;
ok = DeviceIoControl(drvhandle, IOENABLE, message, sizeof(message), NULL, 0, &cb, NULL);
/* We are done - close the handle and return. */
CloseHandle(drvhandle);
if (!ok) {
printf("\a FEJL:
enableAD512():\tKan ikke initialisere Humusoft AD512! (%i)\n",ok);
printf("\n Mulig
grund:\n\tDriver fejl");
}
return(ok ? 0 : -2);
}
/*****************************************************************************
ANALOGINPUT
læser analog
værdi fra analog input kanal
Input: channel:
kanalnummer fra 0-7
range: 0 = 0 - 5
volt
1 = +/- 5 volt
2 = 0 - 10 volt
3 = +/- 10 volt
Output: den læste
værdi 12 bit som en int fra 0-4095
;****************************************************************************/
unsigned short
AnalogInput(int ch, int
range)
{
_outp(AD512BASE+5, ch | (range<<3) |
0x40); //
select channel and range; start the conversion
while
(_inp(AD512BASE+5) & 0x80);
// wait until conversion finishes
return(_inpw(AD512BASE)
& 0xFFF); // return converted value, masking unused bits
}
/*****************************************************************************
ANALOGOUTPUT
skriv en værdi
til analog output
Input channel: kanalnummer
0-1
value: værdi til
output 12 bit 0-4095 (+/- 5 volt)
Output: none
;****************************************************************************/
void AnalogOutput (int ch, int value)
{
unsigned short adresse;
adresse = AD512BASE + 2*ch;
_outpw(adresse, value); //
write the value to D/A converter
_outp(AD512BASE+4, 0); //
update converter output
}
/*****************************************************************************
DIGITALINPUT
læser de digitale
indgange
Input: none
Output: den læste
værdi som en byte hvor hver bit repræsentere en
af de 8 digitale
indgange
;****************************************************************************/
int DigitalInput(void)
{
return(_inp(AD512BASE+7)); //
return value from digital input
}
/*****************************************************************************
DIGITALOUTPUT
skriver en byte
til de digitale udgange
Input: byte hvor
hver bit repræsentere en af de 8 digitale udgange
Output: none
;****************************************************************************/
void DigitalOutput(int value)
{
_outp(AD512BASE+7, value); //
write the value to digital output
}
// Projekt COSS
//
// Fil main.cpp
//
#include "incl.hpp"
void main(int numargs, char *args[]) {
clearDisp();
signal(SIGINT, signalHandler);
signal(SIGABRT, signalHandler);
if
(SetPriorityClass(GetCurrentProcess(), PRIORITY))
cout << " PRIORITY =
" << PRIORITY << " set!" << endl;
if (enableAD512()==0)
{
setDigitalOut(TAEND_2DEC4, false);
cout << " Humusoft AD512
fundet og klar til brug" <<
endl;
initialiser(numargs, args);
clearDisp();
reset();
start();
}
else {
cout << endl << "
Humusoft AD512 blev ikke fundet!" << endl << " Tryk p\x86
en vilk\x86rlig tast for at afslutte";
getch();
}
}
// Projekt COSS
//
// Fil func.cpp
//
#include
"incl.hpp"
#include
"globaleVar.hpp"
void
clearDisp() {
setTextColor(BACK_COLOR
| FOREGROUND_BLACK);
system("cls");
}
bool
doser() {
moveCursorXY(XOFFSET,YOFFSET+STATUS_TEXT_OFFSET);
cout
<< " Doserer vand og saft!";
if (commonChecks(POSITION_DOS)) {
kopStatus(true, BRUGT_KOP);
DWORD
vandSkaenkeTid = ((((getVandVolumen() - 14.7) *1000 / -2424) * 1000)*5/6);
DWORD
saftSkaenkeTid = ((((getSaftVolumen() - 14.7) *1000 / -2424) * 1000)*1/6);
DWORD
vandEndeligTid = (getTid() + vandSkaenkeTid);
DWORD
saftEndeligTid = (getTid() + saftSkaenkeTid);
setDigitalOut(VENTIL_VAND,
true);
setDigitalOut(VENTIL_SAFT,
true);
bool saftDoseret = false;
bool vandDoseret = false;
unsigned int startTid
= getTid();
while (!vandDoseret) {
DWORD
tid = getTid();
if ((tid >= saftEndeligTid) & !saftDoseret) {
setDigitalOut(VENTIL_SAFT,
false);
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+1);
cout
<< " Saft doseret (" << (tid-startTid) << "
ms)" << CLEAR << endl;
saftDoseret
= true;
}
if (tid >= vandEndeligTid) {
setDigitalOut(VENTIL_VAND,
false);
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+2);
cout
<< " Vand doseret (" << (tid-startTid) << "
ms)" << CLEAR << endl;
vandDoseret
= true;
}
if (getResetAktiv() || getDigitalIn(KopIHolder, false)) {
reset();
return false;
}
showStatus();
}
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+3);
cout
<< " Afdrypning i " << (AFDRYP_TID /1000) << "
sekunder";
vandEndeligTid
= getTid()+AFDRYP_TID;
while (getTid() <= vandEndeligTid)
showStatus();
return true;
}
return false;
}
void
initialiser(int numargs, char *args[]) {
if (numargs == 1) {
char svar;
cout
<< "\n Kalibrering? (j/n): ";
svar
= tolower(getche());
if (svar == 'j') {
cout
<< "\n VAND 2 L! (";
getch();
min_vand
= getVandNiveau();
avand
= -1*min_vand;
cout
<< min_vand << ")";
cout
<< "\n VAND 6 L! (";
getch();
avand
+= max_vand = getVandNiveau();
cout
<< max_vand << ")";
avand
/= 4;
cout
<< "\n SAFT 2 L! (";
getch();
min_saft
= getSaftNiveau();
asaft
= -1*min_saft;
cout
<< min_saft << ")";
cout
<< "\n SAFT 6 L! (";
getch();
asaft
+= max_saft = getSaftNiveau();
cout
<< min_saft << ")";
asaft
/= 4;
}
}
else if (numargs = 7)
{
int i = 1;
asaft
= atoi(args[i++]);
avand
= atoi(args[i++]);
min_saft
= atoi(args[i++]);
max_saft
= atoi(args[i++]);
min_vand
= atoi(args[i++]);
max_vand
= atoi(args[i++]);
cout
<< min_vand << max_vand << min_saft << max_saft
<< endl;
}
}
void
koerSlaede(short dir) {
setDigitalOut(STEPMOTOR_DIR,
dir);
setDigitalOut(STEPMOTOR_HOLD_L,
true);
}
bool
kopStatus(bool gemme, bool
status) {
static bool
kop_status = BRUGT_KOP;
if (gemme)
kop_status
= status;
return(kop_status);
}
void
moveCursorXY(DWORD X, DWORD Y) {
COORD
point = {X,Y};
HANDLE
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hConsole,
point);
}
void
printTrueFalse(bool value) {
if (value) {
setTextColor(BACK_COLOR
| FOREGROUND_GREEN | FOREGROUND_INTENSITY);
cout
<< "Ja ";
setTextColor(BACK_COLOR
| TEXT_COLOR);
}
else {
setTextColor(BACK_COLOR
| FOREGROUND_RED);
cout
<< "Nej";
setTextColor(BACK_COLOR
| TEXT_COLOR);
}
}
void printTrueFalse(bool value, float
out) {
if (value)
setTextColor(BACK_COLOR
| FOREGROUND_GREEN | FOREGROUND_INTENSITY);
else
setTextColor(BACK_COLOR
| FOREGROUND_RED);
cout
<< setprecision(1) << setiosflags(ios::fixed | ios::showpoint )
<< out;
setTextColor(BACK_COLOR
| TEXT_COLOR);
}
void
reset() {
bool onOff = (digital_udgang & TAEND_2DEC4) /
TAEND_2DEC4;
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET);
cout
<< " Reset!" << CLEAR;
setDigitalOut(VENTIL_VAND,
false);
setDigitalOut(VENTIL_SAFT,
false);
setDigitalOut(STEPMOTOR_HOLD_L,
false);
DWORD
sleepTid = getTid();
DWORD
blinkTid = 0;
while (sleepTid+AFDRYP_TID >= getTid()) {
if (getTid() > blinkTid+100) {
onOff
= !onOff;
setDigitalOut(TAEND_2DEC4,onOff);
blinkTid
= getTid();
}
showStatus();
}
if (!checkPos(POSITION_START)) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+1);
cout
<< " K\x9Brer til POS_START" << CLEAR << endl;
koerSlaede(TILBAGE);
while (!checkPos(POSITION_START)) {
if (getTid() > blinkTid+100) {
onOff
= !onOff;
setDigitalOut(TAEND_2DEC4,onOff);
blinkTid
= getTid();
}
if (getResetAktiv()) {
reset();
break;
}
showStatus();
}
}
setDigitalOut(STEPMOTOR_HOLD_L,
false);
setDigitalOut(TAEND_2DEC4,true);
}
void
showStatus() {
int linienr = 0;
moveCursorXY(XOFFSET,
YOFFSET+linienr++);
cout<<
" COSS status:";
moveCursorXY(XOFFSET,
YOFFSET+linienr++);
setTextColor(BACK_COLOR
| FOREGROUND_BLACK);
cout
<< TOPLEFT;
for (int i = 1;
i<CONWIDTH; i++) {
if (i == CONMID)
cout
<< TOPMID;
else
cout
<< HORLINE;
}
cout
<< TOPRIGHT;
moveCursorXY(XOFFSET,
YOFFSET+linienr++);
cout << VERLINE;
setTextColor(BACK_COLOR | TEXT_COLOR); cout << "
Kopholderposition ";
setTextColor(BACK_COLOR
| FOREGROUND_BLACK); moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout
<< "\xB3 "; setTextColor(BACK_COLOR | TEXT_COLOR);
getKopHolderPos(); moveCursorXY(XOFFSET+CONWIDTH, YOFFSET+linienr-1);
setTextColor(BACK_COLOR | FOREGROUND_BLACK); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< VERLINE; setTextColor(BACK_COLOR | TEXT_COLOR); cout << "
Kop i kopholder? ";
setTextColor(BACK_COLOR |
FOREGROUND_BLACK); moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout
<< "\xB3 "; setTextColor(BACK_COLOR | TEXT_COLOR);
printTrueFalse(checkKopIHolder()); moveCursorXY(XOFFSET+CONWIDTH, YOFFSET+linienr-1);
setTextColor(BACK_COLOR | FOREGROUND_BLACK); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< VERLINE; setTextColor(BACK_COLOR | TEXT_COLOR); cout << "
Skiftet kop? ";
setTextColor(BACK_COLOR |
FOREGROUND_BLACK); moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout
<< "\xB3 "; setTextColor(BACK_COLOR | TEXT_COLOR);
printTrueFalse(kopStatus(false, false)); moveCursorXY(XOFFSET+CONWIDTH,
YOFFSET+linienr-1); setTextColor(BACK_COLOR | FOREGROUND_BLACK); cout <<
VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< VERLINE; setTextColor(BACK_COLOR | TEXT_COLOR); cout << "
Startknap aktiv? ";
setTextColor(BACK_COLOR | FOREGROUND_BLACK);
moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout << "\xB3 ";
setTextColor(BACK_COLOR | TEXT_COLOR); printTrueFalse(getStartAktiv());
moveCursorXY(XOFFSET+CONWIDTH, YOFFSET+linienr-1); setTextColor(BACK_COLOR |
FOREGROUND_BLACK); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< VERLINE; setTextColor(BACK_COLOR | TEXT_COLOR); cout << "
Resetknap aktiv? ";
setTextColor(BACK_COLOR |
FOREGROUND_BLACK); moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout
<< "\xB3 ";
setTextColor(BACK_COLOR | TEXT_COLOR); printTrueFalse( getResetAktiv());
moveCursorXY(XOFFSET+CONWIDTH,YOFFSET+linienr-1); setTextColor(BACK_COLOR |
FOREGROUND_BLACK); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< VERLINE; moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout <<
"\xB3";
moveCursorXY(XOFFSET+CONWIDTH,
YOFFSET+linienr-1); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout << VERLINE;
setTextColor(BACK_COLOR | TEXT_COLOR); cout << " Vand
temperatur ";
setTextColor(BACK_COLOR |
FOREGROUND_BLACK); moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout
<< "\xB3 ";
setTextColor(BACK_COLOR | TEXT_COLOR); printTrueFalse(
(getVandTemp()<=16.0), getVandTemp()); cout << " \xF8\C ";
moveCursorXY(XOFFSET+CONWIDTH,YOFFSET+linienr-1); setTextColor(BACK_COLOR |
FOREGROUND_BLACK); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< VERLINE; setTextColor(BACK_COLOR | TEXT_COLOR); cout << "
Vandm\x91ngde ";
setTextColor(BACK_COLOR | FOREGROUND_BLACK);
moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout << "\xB3 "; setTextColor(BACK_COLOR |
TEXT_COLOR); printTrueFalse( (getVandVolumen() >= 2), getVandVolumen());
cout << " L ";
moveCursorXY(XOFFSET+CONWIDTH,YOFFSET+linienr-1); setTextColor(BACK_COLOR |
FOREGROUND_BLACK); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< VERLINE; setTextColor(BACK_COLOR | TEXT_COLOR); cout << "
Saftm\x91ngde ";
setTextColor(BACK_COLOR |
FOREGROUND_BLACK); moveCursorXY(XOFFSET+CONMID,YOFFSET+linienr-1); cout
<< "\xB3 ";
setTextColor(BACK_COLOR | TEXT_COLOR); printTrueFalse( (getSaftVolumen() >=
2), getSaftVolumen()); cout << " L "; moveCursorXY(XOFFSET+CONWIDTH,YOFFSET+linienr-1);
setTextColor(BACK_COLOR | FOREGROUND_BLACK); cout << VERLINE;
moveCursorXY(XOFFSET, YOFFSET+linienr++);
cout
<< BUTTOMLEFT;
for (int i = 1;
i<CONWIDTH; i++) {
if (i == CONMID)
cout
<< BUTTOMMID;
else
cout
<< HORLINE;
}
cout
<< BUTTOMRIGHT << endl;
}
void
signalHandler(int signal) {
char sasaft[5];
_itoa(asaft,
sasaft, 10);
char savand[5];
_itoa(avand,
savand, 10);
char smin_saft[5];
_itoa(min_saft,
smin_saft, 10);
char smax_saft[5];
_itoa(max_saft,
smax_saft, 10);
char smin_vand[5];
_itoa(min_vand,
smin_vand, 10);
char smax_vand[5];
_itoa(max_vand,
smax_vand, 10);
DigitalOutput(0);
_spawnl(_P_NOWAIT,
myProg, myProg_path, sasaft, savand, smin_saft, smax_saft, smin_vand,
smax_vand, NULL);
exit(-1);
}
void
start() {
while (true) {
clearDisp();
while (!getStartAktiv()) {
showStatus();
if (resetAktiv = getResetAktiv()) {
reset();
clearDisp();
}
if (_kbhit()) {
char c = _getch();
if (c == 'S')
break;
else if (c == 'K')
kopStatus(true, true);
}
}
showStatus();
if (!commonChecks(POSITION_START))
reset();
else if (!(resetAktiv
= getResetAktiv())) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET);
cout
<< " K\x9Brer til POS_DOS" << CLEAR << endl;
koerSlaede(FREM);
while (!checkPos(POSITION_DOS)) {
if ((resetAktiv = getResetAktiv()) ||
!checkKopIHolder()) {
reset();
break;
}
showStatus();
}
setDigitalOut(STEPMOTOR_HOLD_L,
false);
if (!resetAktiv)
doser();
if (!resetAktiv) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET);
cout
<< " K\x9Brer til POS_START" << CLEAR << endl;
koerSlaede(TILBAGE);
while (!checkPos(POSITION_START)) {
if ((resetAktiv = getResetAktiv()) ||
!checkKopIHolder()) {
reset();
break;
}
showStatus();
}
setDigitalOut(STEPMOTOR_HOLD_L,
false);
}
}
}
}
///////////////////////////////////
// check funktioner !! //
///////////////////////////////////
bool
checkPos(int position) {
if (position != POSITION_START & position !=
POSITION_DOS) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET);
cout
<< "FEJL: checPos():\tUlovlig position: " << position
<< endl;
return false;
}
else if
(getDigitalIn(POS_START, true)) {
setDigitalOut(DECODER_1,
false);
setDigitalOut(DECODER_2,
false);
if (position == POSITION_START) {
return true;
}
else
return false;
}
else if
(getDigitalIn(POS_DOS, true)) {
setDigitalOut(DECODER_1,
false);
setDigitalOut(DECODER_2,
true);
if (position == POSITION_DOS) {
return true;
}
else
return false;
}
else if
((digital_udgang & STEPMOTOR_DIR) / STEPMOTOR_DIR == TILBAGE) {
setDigitalOut(DECODER_1+DECODER_2,true);
return false;
}
else {
setDigitalOut(DECODER_1,true);
setDigitalOut(DECODER_2,false);
return false;
}
}
bool checkKopIHolder()
{
if (!getDigitalIn(KopIHolder, true)) {
if (checkPos(POSITION_START)) {
kopStatus(true, TOM_KOP);
}
return false;
}
return true;
}
bool
commonChecks(int position) {
bool value = true;
int linienr = 2;
if (!checkKopIHolder()) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tDer er ikke nogen kop i
kopholderen";
value
= false;
}
if ( checkPos(POSITION_START) ) {
if (!(position==POSITION_START)) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tKopholder er ikke i POS_START";
value
= false;
}
else if
(getVandTemp() > 16.0 ) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tTemperaturen er over 16 \xF8\C";
value
= false;
}
}
else {
if ( !checkPos(POSITION_DOS)) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tKopholder er ikke i POS_DOS";
value
= false;
}
}
if (getResetAktiv()) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tReset er aktiv";
value
= false;
}
if (kopStatus(false, false) == BRUGT_KOP) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tKoppen har v\x91ret brugt!";
value
= false;
}
if (getVandVolumen() < 2.0) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tDer er for lidt vand!";
value
= false;
}
if (getSaftVolumen() < 2.0) {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET+linienr++);
cout
<< " FEJL: CommonChecks():\tDer er for lidt saft!";
value
= false;
}
return value;
}
///////////////////////////////
// get funktioner !! //
///////////////////////////////
int
getAnalogIn(short kanal) {
if (kanal > 7 || kanal < 0) {
cout
<< " FEJL: getAnalogIn():\tKanalen eksisterer ikke: " <<
kanal;
return (-1);
}
return AnalogInput(kanal, 0);
}
bool
getDigitalIn(short kanal, bool value) {
int tal = DigitalInput();
tal
= tal & kanal;
if (tal > 0)
tal
= tal / kanal;
return (tal == value );
}
bool
getKopHolderPos() {
if (checkPos(POSITION_START)) {
cout
<< "Start ";
return true;
}
else if (checkPos(POSITION_DOS))
{
cout
<< "Dosering ";
return true;
}
else if
((digital_udgang & STEPMOTOR_DIR) / STEPMOTOR_DIR == TILBAGE) {
cout
<< "Dosering -> Start";
return false;
}
else {
cout
<< "Start -> Dosering";
return false;
}
}
bool
getResetAktiv() { //Aktiv lav
return (getDigitalIn(RESET_AKTIV, false) );
}
int
getSaftNiveau() {
return (getAnalogIn(SAFT) );
}
float
getSaftVolumen() {
float saftVol =
(((getSaftNiveau()-min_saft)+asaft*2.0)/asaft);
if (saftVol < 0)
return 0;
else
return saftVol;
}
bool
getStartAktiv() { //Aktiv lav
return (getDigitalIn(START_AKTIV, false) );
}
DWORD getTid() {
struct __timeb64 timebuffer;
_ftime64(
&timebuffer );
return (timebuffer.time * 1000 + timebuffer.millitm);
}
int
getVandNiveau() {
return (getAnalogIn(VAND) );
}
float
getVandTemp() {
float temp = (getAnalogIn(TEMP) );
float tempCelcius = (temp * 49.054/4096) -
TEMPOFFSET;
if (tempCelcius > 16)
setDigitalOut(DECODER_3,true);
else
setDigitalOut(DECODER_3,false);
setAnalogOut(0,
DAOFFSET + temp/2);
if (tempCelcius < 0)
return 0;
return tempCelcius;
}
float
getVandVolumen() {
float vandVol =
((getVandNiveau()-min_vand)+avand*2.0)/avand;
if (vandVol < 0)
return 0;
else
return vandVol;
}
///////////////////////////////
// set funktioner !! //
///////////////////////////////
void
setDigitalOut(short kanal, bool value) {
if (((kanal & digital_udgang) / kanal) == value)
{}
else {
if (value == true) {
digital_udgang
= digital_udgang | kanal;
}
else {
digital_udgang
= digital_udgang - kanal;
}
if (digital_udgang < 0)
digital_udgang
= 0;
}
DigitalOutput(digital_udgang);
}
void
setAnalogOut(short kanal, short value) {
if ((value >= 0) & (value < 4096))
AnalogOutput
(kanal, value);
else {
moveCursorXY(XOFFSET,
YOFFSET+STATUS_TEXT_OFFSET);
cout
<< " FEJL: setAnalogOut(): value er forkert" << endl;
}
}
void
setTextColor(DWORD dwAttributes) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
dwAttributes);
}
MODULE Stpmtrst
declarations
clock, hold, dir PIN 1, 2, 3;
Q1..Q2 PIN 23,22 istype 'reg';
ibuf PIN 6;
obuf PIN 19 istype 'com';
iinv1, iinv2 PIN 4,5;
inv1 , inv2 PIN 20,21
istype 'com';
taend_2dec4 PIN 8;
ibit1,ibit2,ibit3 PIN 9,10,11;
obit1,obit2,obit3,obit4,obit5 PIN 18..14 istype 'com';
x,c = .x.,.c.;
QSTATE =[Q1,Q2];
s00 = [0,0];
s01 = [0,1];
s11 = [1,1];
s10 = [1,0];
equations
QSTATE.CLK = clock;
QSTATE.OE = [1,1];
"2-4 decoder
obit1 = (!ibit2 & !ibit1)
& taend_2dec4;
obit2 = (!ibit2 & ibit1)
& taend_2dec4;
obit3 = (ibit2 & !ibit1)
& taend_2dec4;
obit4 = (ibit2 & ibit1)
& taend_2dec4;
"vaeske varm
obit5 = ibit3;
"inverter
inv1 = !iinv1;
inv2 = !iinv2;
"buffer
obuf = ibuf;
state_diagram QSTATE
state s00:" a=0; b=0;
if dir & hold then s01 else
if hold then s10
else s00;
state s01:" a=0; b=1;
if dir & hold then s11 else
if hold then s00
else s01;
state s11:" a=1; b=1;
if dir & hold then s10 else
if hold then s01
else s11;
state s10:" a=1; b=0;
if dir & hold then s00 else
if hold then s11
else s10;
test_vectors
([ hold,
dir, clock] -> [QSTATE,Q1,Q2])
[x,x,0] -> [s00,0,0];
[0,x,c] -> [s00,0,0];
[1,1,c] -> [s01,0,1];
[0,x,c] -> [s01,0,1];
[1,1,c] -> [s11,1,1];
[0,x,c] -> [s11,1,1];
[1,1,c] -> [s10,1,0];
[0,x,c] -> [s10,1,0];
[1,1,c] -> [s00,0,0];
[0,x,c] -> [s00,0,0];
[1,0,c] -> [s10,1,0];
[0,x,c] -> [s10,1,0];
[1,0,c] -> [s11,1,1];
[0,x,c] -> [s11,1,1];
[1,0,c] -> [s01,0,1];
[0,x,c]
-> [s01,0,1];
[1,0,c] -> [s00,0,0];
[0,x,c] -> [s00,0,0];
test_vectors
([ibit2,ibit1,ibit3,taend_2dec4]
-> [obit1,obit2,obit3,obit4,obit5])
[0,0,0,1] -> [1,0,0,0,0];
[0,0,1,1] -> [1,0,0,0,1];
[0,1,0,1] -> [0,1,0,0,0];
[1,0,1,1] -> [0,0,1,0,1];
[1,1,0,1] -> [0,0,0,1,0];
[1,1,0,0] -> [0,0,0,0,0];
[1,1,1,0] -> [0,0,0,0,1];
END
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 11.09.02 - Uge 37 |
Møde nummer: 01 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 16.09.02 - Uge 38 |
Møde nummer: 02 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 18.09.02 – Uge 38 |
Møde nummer: 03 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 23.09.02 – Uge 39 |
Møde nummer: 04 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 30.09.02 – Uge 40 |
Møde nummer: 05 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 07.10.02 – Uge 41 |
Møde nummer: 06 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 21.10.02 – Uge 43 |
Møde nummer: 07 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 28.10.02 – Uge 44 |
Møde nummer: 08 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 04.11.02 – Uge 45 |
Møde nummer: 09 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 11.11.02 – Uge 46 |
Møde nummer: 10 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 18.11.02 – Uge 47 |
Møde nummer: 11 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 25.11.02 – Uge 48 |
Møde nummer: 12 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 09.12.02 – Uge 50 |
Møde nummer: 13 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 12.12.02 – Uge 50 |
Møde nummer: 14 |
|
Mødereferat for projekt |
|
|
Gruppe 1, semester I1 |
|
|
Dato: 16.12.02 – Uge 51 |
Møde nummer: 15 |