Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006)

.pdf
Скачиваний:
192
Добавлен:
12.08.2013
Размер:
3.18 Mб
Скачать

316 10 VOLTAGE AND TEMPERATURE MEASUREMENT

{

outportb(BaseAddress+2,data ^ 0x0B);

}

unsigned char ParallelPort::ReadPort1()

{

InDataPort1 = inportb(BaseAddress+1);

//Inverting Most significant bit to compensate

//for internal inversion by printer port hardware. InDataPort1 ^= 0x80;

//Filter to clear unused data bits D0, D1 and D2 to zero. InDataPort1 &= 0xF8;

return InDataPort1;

}

So far we haven’t created a header file and a function file for the DAC module. These files are given in Listing 10-9 and Listing 10-10 respectively.

Listing 10-9 The header file for the DAC class - dac.h.

#ifndef DacH #define DacH

#include "pport.h"

class DAC : public ParallelPort

{

private:

unsigned char LastOutput;

public:

DAC();

DAC(int baseaddress);

void SendData(unsigned char data); unsigned char GetLastOutput(); ~DAC(){};

};

#endif

Listing 10-10 The function file for the DAC class - dac.cpp.

#include "dac.h"

10 VOLTAGE AND TEMPERATURE MEASUREMENT 317

DAC::DAC()

{

LastOutput = 0;

}

DAC::DAC(int baseaddress) : ParallelPort(baseaddress)

{

LastOutput = 0;

}

void DAC::SendData(unsigned char data)

{

ParallelPort::WritePort0(data); LastOutput = data;

}

unsigned char DAC::GetLastOutput()

{

return LastOutput;

}

Executable File Generation

 

Required Files

 

Listing No.

 

Project File Contents

 

 

pport.cpp

 

Listing 10-8

 

pport.cpp

 

 

 

 

 

 

pport.h

 

Listing 10-7

 

 

 

 

vco.cpp

Listing 10-4

 

vco.cpp

 

vco.h

Listing 10-1

 

dac.cpp

 

dac.cpp

Listing 10-10

 

 

 

dac.h

Listing 10-9

 

 

 

 

period.cpp

Listing 10-6

 

period.cpp

 

The table shown above lists all the files needed to form the executable file that should be stored in the one directory. Form a project file using the program development environment of your choice and add the files that are listed in the column titled ‘Project File Contents’. Then the compiler and linker can be directed to form the executable file. Tables such as the one shown above will be provided in this text whenever modules must be combined to form an executable file.

Make the connections on the interface board as shown in Table 10-1 to Table 10-3 before executing the program. These tables list the wiring needed to control the DAC and the VCO. Set the DAC output to unipolar mode by fitting the jumper across the position on the board marked LINK1. Remember to connect an operational 9V battery to its terminal block (J14) to allow proper DAC operation. Note that the VCO response is linear (typically 1%) for input voltages in the range

318 10 VOLTAGE AND TEMPERATURE MEASUREMENT

of 2.2V to 2.8V. Although linearity deteriorates outside this range, the VCO can be characterised across its entire input range and used effectively.

Table 10-1 Connections for the DAC.

BASE Address

DAC0800

(Buffer IC, U13)

(U8)

D0

D0 (12)

D1

D1

(11)

D2

D2

(10)

D3

D3

(9)

D4

D4

(8)

D5

D5

(7)

D6

D6

(6)

D7

D7

(5)

Table 10-2 INPUT connections for the VCO.

LM358

VCO

(U10B)

(4046, U4)

 

 

VDAC (7)

VIN (9)

 

 

NOTE

Table 10-3 OUTPUT connections for the VCO.

VCO

BASE+1 Address

(4046, U4)

(Buffer IC, U6)

 

 

VCO OUTPUT (4)

D3

 

 

If any malfunction occurs; first check the 9V battery is operational – its voltage

should be greater than 7V when it is being used.

10.6 Graphics Programming – Square

Wave Display

A program was developed in Section 10.5 that can measure the period of the square wave generated by the VCO and produce a simple numerical output. In this section we will use graphics programming to generate a graphical display so the user can visualise the signal’s waveform.

10 VOLTAGE AND TEMPERATURE MEASUREMENT 319

The potentiometer circuit on the interface board provides a very convenient means of generating an analog voltage to apply to the input of the VCO. Varying the position of the potentiometer will change its output voltage (0V to +5V) and hence change the output frequency of the VCO. The connections that need to be made between the potentiometer and the VCO are shown in Table 10-4 and Table 10-5.

Table 10-4 INPUT connections for the VCO.

Potentiometer

VCO

(POT1)

(4046, U4)

OUTPUT

VIN (9)

Table 10-5 OUTPUT connections for the VCO.

VCO

BASE+1 Address

(4046, U4)

(Buffer IC, U6)

VCO OUTPUT (4)

D3

 

 

10.6.1 Screen Programming

This program to be developed will display the signal from the VCO as a waveform inside a fixed area of the screen. The waveform being displayed will trace across the screen similar to the trace of an oscilloscope. This must happen in real-time; the changes shown on-screen matching the instantaneous changes of the VCO signal.

The standard library provides many graphics routines for our program to use. These routines can determine which graphics driver should be used, the appropriate graphics mode, the maximum number of pixels in x and y directions, etc. The screen uses an array of pixels, where each pixel is one element of the screen that is individually illuminated to form part of the picture. Because different screens contain different numbers of pixels, it is often necessary to determine the screen’s pixel count before deciding the size of the display area to be used by a program.

In any graphics program running under DOS, the system must first be configured in a graphics mode that uses a graphics driver. A driver is a module of executable code that is used to drive the actual graphics output. These drivers can operate in different modes that set the number of pixels used in x and y directions, and set which colour palette to use. The program must set the system in a suitable graphics mode and then determine the number of pixels in the x and y directions. This information allows the program to calculate the screen coordinates needed to centre the waveform on-screen inside the area known as the Viewport. Figure 10-6 shows the screen coordinates and the calculations performed by the program’s functions to generate the waveform.

320 10 VOLTAGE AND TEMPERATURE MEASUREMENT

Positive x

y

Origin (0,0)

Screen

-75

 

Positive

 

Boundary

getmaxy()/2

 

Viewport

 

getmaxy()/2 +75

Origin (0,0)

Viewport

 

 

 

 

Displayed

 

 

 

getmaxx()*1/4

Waveform

 

 

 

 

 

 

 

 

getmaxx()*3/4

 

 

Figure 10-6 Arrangement to display the VCO output.

The program will use half of the x pixel-range and one hundred and fifty pixels in the vertical direction for its Viewport, centred on-screen in both the horizontal and vertical directions. We have separated the high and low levels of the waveform by 50 pixels in the vertical direction. The functions getmaxx() and getmaxy() are functions that can be used to determine the number of pixels in the x and y directions. The Viewport is now established (with its origin located at its upper left-most corner).

The waveform can be plotted as a line joining sequential points, explained as follows (note: the positive y direction is down). When the port is read; if the signal level is high, the Y coordinate of the current point will be 50 pixels in the y direction from the Viewport Origin. If the signal level is low, the Y coordinate will be 100 pixels in the y direction from the Viewport Origin. The first VCO value read will be plotted 0 pixels from the Viewport Origin in the x direction. The next point will be plotted at x=1, the following at 2, and so on. When we reach the end in the x direction, we must re-start plotting from x=0, but not before erasing the current waveform being displayed. This plotting process will repeat continuously until the program detects a keypress and then terminates.

The required program steps can be listed as follows:

1.Initialise graphics and set the graphics mode.

2.Determine the maximum number of pixels in the x and y directions.

3.Configure the Viewport.

4.Enter a while loop conditioned on !kbhit(). If any key is pressed, terminate the program.

10 VOLTAGE AND TEMPERATURE MEASUREMENT 321

5.Read the port and obtain the output signal level of the VCO.

6.Plot the pixel according to the signal level (high or low) and increment the x pixel count.

7.If the x pixel count has not reached the end of its range, return to step 4. Else, reset the x pixel count to restart plotting, clear the view port, and return to step 4.

A program that carries out the above set of tasks is given in Listing 10-11. The appearance of the program’s display is basic and could be improved by adding some finishing touches.

Listing 10-11 Graphically display the VCO output – trace.cpp.

/***************************************************** The frequency of the pulse-train being output by the voltage-controlled oscillator will change as we change the analog input voltage to the VCO circuit. The Potentiometer (POT1) on the interface board generates the input voltage to the VCO and the program reads the pulse-train being output by the VCO. This pulse-train is graphically displayed on-screen.

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

#include <graphics.h> #include <stdlib.h> #include <iostream.h> #include <conio.h> #include <dos.h>

#include "vco.h"

void main()

{

VCO Vco;

int i=0; // controls plotting in the x range int SignalLevel;

int Driver = DETECT, GraphicsMode, ErrorCode; int X, Y;

//set to graphics mode initgraph(&Driver, &GraphicsMode, "");

//check for error codes

ErrorCode = graphresult(); if (ErrorCode != grOk)

{

322 10 VOLTAGE AND TEMPERATURE MEASUREMENT

cout << "Graphics error: "

<< grapherrormsg(ErrorCode) << endl; cout << "Press any key to halt:" << endl; getch();

exit(1);

}

X = getmaxx(); Y = getmaxy();

rectangle(X/4-1, Y/2-76,X*3/4+1,Y/2+76); // border setviewport(X/4, Y/2-75,X/4*3,Y/2+75,1);

while(!kbhit())

{

SignalLevel = Vco.SignalLevel(); if(SignalLevel == 0) // low level

lineto(i,100);

else // high level lineto(i,50);

i++;

delay(2);

if(i > X/2) // half screen = Viewport width

{

i = 0;

while(Vco.SignalLevel()); // wait for low level

// wait for signal level to go high again while(!Vco.SignalLevel()); clearviewport();

}

}

}

Executable File Generation

 

Required Files

 

 

Listing No.

 

Project File Contents

 

 

 

pport.cpp

 

 

Listing 10-8

 

pport.cpp

 

 

 

 

 

 

 

 

 

pport.h

 

Listing 10-7

 

vco.cpp

 

 

 

vco.cpp

 

Listing 10-4

 

 

 

vco.h

 

Listing 10-1

 

 

 

 

trace.cpp

 

Listing 10-11

 

trace.cpp

 

 

10 VOLTAGE AND TEMPERATURE MEASUREMENT 323

The file graphics.h is needed for all graphics-related routines such as initgraph(), grapherror(), moveto(), lineto(), etc, and for use of the constants DETECT and grOk. The class VCO is used to create an instance of VCO named Vco as in the previous program. Several variables of type int are declared inside main(). Variables X and Y will initially be used to store the maximum number of pixels in x and y directions respectively. At later stages in the program they will be used for other purposes. Variable i is used to control plotting of pixels in the Viewport’s x range. It will be reset to 0 for the start of a new plot when the trace reaches the end of the Viewport range.

The variables Driver and GraphicsMode are explained together with the initgraph() function. The first parameter to initgraph() must specify the type of graphics driver. The driver could be for the Colour Graphics Adapter (CGA), Enhanced Graphics Adapter (EGA), Video Graphics Array (VGA), etc. If the value of Driver is set to 1, then CGA is specified; if it is set to 2, EGA is specified. A description of these constants should be found in the documentation for initgraph(). A number of graphics modes will be available for each driver to generate the resolution (number of pixels) and the colour palette used. For example; 16 colour, 640 x 480 screen resolution is specified by assigning GraphicsMode the value 2. If GraphicsMode is assigned the value 1, the screen will use 16 colours and a resolution of 640 x 320. However, when the value of Driver is set to DETECT (predefined to be 0), the program will automatically detect the driver suitable for the computer’s graphics card and set the resolution to the highest available. In this situation, GraphicsMode does not need to be assigned a value. The third parameter to initgraph() is a string specifying the path to the graphics driver, in this case the location of the file EGAVGA.BGI. If the graphics driver is in your current directory (the directory where you have your executable file) then this field can have an empty string. Note that, when the call to initgraph() is made, the first two arguments are preceded by the & character. This is needed because initgraph() takes these arguments as pointers (i.e. an address value).

To determine if initgraph() has successfully completed its task, we call graphresult() and store the value returned by graphresult() in ErrorCode. If ErrorCode is not equal to the predefined constant grOk, then an error has occurred. A message corresponding to the value in ErrorCode can be generated by calling grapherrormsg(). The true clause of the if statement will display the error messages and then call the exit() function to terminate the program. If no errors occurred, program execution will proceed to carry out the next task – to determine the maximum number of pixels in x and y directions. A rectangle will be drawn just one pixel outside the chosen Viewport followed by configuration of the Viewport. As explained previously, the Viewport is the area where the waveform will be displayed. Once the Viewport is established, the origin (0,0) becomes the upper left-corner of the Viewport.

The while loop, conditioned on !kbhit(), is used to continuously display the waveform on-screen. The lineto() function uses the new coordinate frame of

324 10 VOLTAGE AND TEMPERATURE MEASUREMENT

the Viewport. The value of i will be zero when beginning to plot a new trace. A line will be drawn from the previous screen position to the new vertical position determined by the signal level. The x plot position is then incremented for the next plot. When the value of i reaches the end of its range in the x direction (Viewport width = X/2), i is reset to zero for a new plot. The remaining code synchronises the plotting so the next trace will always begin on a low level. The Viewport is then cleared to erase the current trace.

Note that since interrupts are enabled, some of the pulses displayed on-screen may have wider widths due to time consumed by interrupt service routines.

10.7 Temperature Measurement

We measure temperature indirectly by using the analog voltage generated by the thermistor resistive-divider circuit. The voltage being generated drops in a nonlinear manner as the temperature increases whan a negative temperature coefficient thermistor is used in the resistive-divider circuit (as shown in Figure 10-3). To simplify our programming let us approximate the curve by a straight line. We can develop a program that will measure the actual temperature using the same wiring as described in Section 10.6 (except the POT output is replaced with the Thermistor output, VTH). A typical thermistor/VCO relationship is shown in Figure 10-7.

10.7.1 Thermistor Calibration

The program needs to measure the cycle time of the VCO output and interpret this value as temperature. The first task is to calibrate the thermistor. This is done by subjecting the thermistor to known temperatures such as that of ice, the body, and say boiling water to obtain measures of corresponding cycle times. Then we can establish a calibration equation or calibration table which can be used to extrapolate or interpolate values of temperature (within linearity limits of the thermistor/VCO circuit response). Note that the output of the thermistor circuit may extend well beyond the linearity range of the VCO (approximately 1.5V to 3.5V). If the voltage applied to the VCO input is outside its linear range, the output from the VCO will be a distorted measure of the thermistor output. However, the temperature measuring system made up of the thermistor and VCO can still be calibrated and used, but with less accuracy.

The calibration equation can be determined as follows (refer to Figure 10-7). We can add a few extra statements to the program in Listing 10-6 to include a means of entering an upper temperature and a lower temperature. The corresponding cycle times can then be read and a calibration equation can be established. If no upper and lower temperatures are entered (HiTemp and LoTemp), the program will display the cycle time as did the program in Listing 10-6. If calibration has been performed correctly, the program will display the actual temperatures. This feature requires some logic to be built into the program. We can use flags to detect whether

10 VOLTAGE AND TEMPERATURE MEASUREMENT 325

upper and lower temperatures have been entered. If both flags are set; that is, if both temperatures have been entered, we can establish the calibration equation. Then we can display temperature instead of cycle times. We will adhere to using the same keys as for Listing 10-6; Alt-X to quit the program, up arrow to enter an upper temperature, and down arrow to enter a lower temperature.

Temperature

HiCount - LoCount

 

HiTemp

 

HiTemp - LoTemp

Temp

LoTemp

LoCount

i

HiCount

Period in Counts

Figure 10-7 Typical curve - Thermistor circuit/VCO output (calibration).

The program steps can be listed as follows:

1.Initialise a counter to zero.

2.Repeatedly check the signal level until a change is detected.

3.Repeatedly check the signal level until the second change is detected while incrementing the counter after each read.

4.Repeatedly check the signal level until the third change is detected while incrementing the counter after each read.

5.Check if the calibration temperature for upper temperature and lower temperature has been entered (respective flags are both set).

If they are both entered, use the calibration equation and display the temperature, else display the cycle time.

6.Check if a key has been pressed. If no key has been pressed return to step 1.

7.If the pressed key is Alt-X, exit the program.

8.If the up arrow key is pressed, read upper temperature. Return to step 1.

9.If the down arrow key is pressed, read lower temperature. Return to step 1.

Some of these steps can be expanded further as shown below:

8.1Ask user to enter the upper temperature and store value entered.

8.2Store the cycle time.

8.3Set the flag confirming the upper calibration temperature has been read.