PROJECT 6.8—Voltmeter with LCD Display
Project Description
In this project a voltmeter with LCD display is designed. The voltmeter can be used to measure voltages 0–5V. The voltage to be measured is applied to one of the analog inputs of a PIC18F452-type microcontroller. The microcontroller reads the analog voltage, converts it into digital, and then displays it on an LCD.
In microcontroller systems the output of a measured variable is usually displayed using LEDs, 7-segment displays, or LCD displays. LCDs make it possible to display alphanumeric or graphical data. Some LCDs have forty or more character lengths with the capability to display several lines. Other LCD displays can be used to display graphics images. Some modules offer color displays, while others incorporate backlighting so they can be viewed in dimly lit conditions.
There are basically two types of LCDs as far as the interface technique is concerned: parallel and serial. Parallel LCDs (e.g., Hitachi HD44780) are connected to a microcontroller by more than one data line and the data is transferred in parallel form. Both four and eight data lines are commonly used. A four-wire connection saves I/O pins but is slower since the data is transferred in two stages.
Serial LCDs are connected to the microcontroller by only one data line, and data is usually sent to the LCD using the standard RS-232 asynchronous data communication protocol. Serial LCDs are much easier to use, but they cost more than the parallel ones.
The programming of a parallel LCD is a complex task and requires a good understanding of the internal operation of the LCD controllers, including the timing diagrams. Fortunately, the mikroC language provides special library commands for displaying data on alphanumeric as well as graphic LCDs. All the user has to do is connect the LCD to the microcontroller, define the LCD connection in the software, and then send special commands to display data on the LCD.
HD44780 LCD Module
The HD44780 is one of the most popular alphanumeric LCD modules and is used both in industry and by hobbyists. This module is monochrome and comes in different sizes.
Modules with 8, 16, 20, 24, 32, and 40 columns are available. Depending on the model chosen, the number of rows may be 1, 2, or 4. The display provides a 14-pin (or 16-pin) connector to a microcontroller. Table 6.10 gives the pin configuration and pin functions of a 14-pin LCD module. The following is a summary of the pin functions:
VSS is the 0V supply or ground. The VDD pin should be connected to the positive supply. Although the manufacturers specify a 5V DC supply, the modules will usually work with as low as 3V or as high as 6V.
Pin 3, named VEE, is the contrast control pin. This pin is used to adjust the contrast of the display and should be connected to a variable voltage supply. A potentiometer is normally connected between the power supply lines with its wiper arm connected to this pin so that the contrast can be adjusted.
Pin 4 is the register select (RS), and when this pin is LOW, data transferred to the display is treated as commands. When RS is HIGH, character data can be transferred to and from the module.
Pin 5 is the read/write (R/W) line. This pin is pulled LOW in order to write commands or character data to the LCD module. When this pin is HIGH, character data or status information can be read from the module.
Pin 6 is the enable (E) pin, which is used to initiate the transfer of commands or data between the module and the microcontroller. When writing to the display, data is transferred only on the HIGH-to-LOW transition of this line. When reading from the display, data becomes available after the LOW-to-HIGH transition of the enable pin, and this data remains valid as long as the enable pin is at logic HIGH.
Pins 7 to 14 are the eight data bus lines (D0 to D7). Data can be transferred between the microcontroller and the LCD module using either a single 8-bit byte or as two 4-bit nibbles. In the latter case, only the upper four data lines (D4 to D7) are used. The 4-bit mode means that four fewer I/O lines are used to communicate with the LCD. In this book we are using only an alphanumeric-based LCD and only the 4-bit interface.
Connecting the LCD
The mikroC compiler assumes by default that the LCD is connected to the microcontroller as follows:
where port is the port name specified using the Lcd_Init statement.
For example, we can use the statement Lcd_Init(&PORTB) if the LCD is connected to PORTB with the default connection.
It is also possible to connect the LCD differently, using the command Lcd_Config to define the connection.
Project Hardware
Figure 6.38 shows the block diagram of the project. The microcontroller reads the analog voltage, converts it to digital, formats it, and then displays it on the LCD.
The circuit diagram of the project is shown in Figure 6.39. The voltage to be measured (between 0 and 5V) is applied to port AN0 where this port is configured as an analog
input in software. The LCD is connected to PORTC of the microcontroller as in the default four-wire connection. A potentiometer is used to adjust the contrast of the LCD display.
Project PDL
The PDL of the project is shown in Figure 6.40. At the beginning of the program PORTC is configured as output and PORTA is configured as input. Then the LCD and the A/D converter are configured. The program then enters an endless loop where analog input voltage is converted to digital and displayed on the LCD. The process is repeated every second.
Project Program
The program is called SEVEN6.C, and the program listing is given in Figure 6.41. At the beginning of the program PORTC is defined as output and PORTA as input.
Then the LCD is configured and the text “VOLTMETER” is displayed on the LCD for two seconds. The A/D is then configured by setting register ADCON1 to 0x80 so the A/D result is right-justified, Vref voltage is set to VDD (þ5V), and all PORTA pins are configured as analog inputs.
The main program loop starts with a for statement. Inside this loop the LCD is cleared, and analog data is read from channel 0 (pin AN0) using the statement Adc_Read(0). The converted digital data is stored in variable Vin which is declared as an unsigned long. The A/D converter is 10-bits wide and thus there are 1024 steps
(0 to 1023) corresponding to the reference voltage of 5000mV. Each step corresponds to 5000mV/1024 ¼ 4.88mV. Inside the loop, variable Vin is converted into millivolts by multiplying by 5000 and dividing into 1024. The division is done by shifting right by 10 digits. At this point variable mV contains the converted data in millivolts.
Function LongToStr is called to convert mV into a string in character array op. LongToStr converts a long variable into a string having a fixed width of eleven characters. If the resulting string is fewer than eleven characters, the left column of the data is filled with space characters.
The leading blanks are then removed and the data is stored in a variable called lcd. Function Lcd_Out is called to display the data on the LCD starting from column 5 of row 1. For example, if the measured voltage is 1267mV, it is displayed on the LCD as:
A More Accurate Display
The voltage displayed in Figure 6.41 is not very accurate, since integer arithmetic has been performed in the calculation and the voltage is calculated by multiplying the A/D output by 5000 and then dividing the result by 1024 using integer division.
Although the multiplication is accurate, the accuracy of the measurement is lost when the number is divided by 1024. A more accurate result can be obtained by scaling the number before it is displayed, as follows.
First, multiply the number Vin by a factor to remove the integer division. For example, since 5000/1024 ¼ 4.88, we can multiply Vin by 488. For the display, we can calculate the integer part of the result by dividing the number into 100, and then the fractional part can be calculated as the remainder. The integer part and the fractional part can be displayed with a decimal point in between. This technique has been implemented in program SEVEN7.C as shown in Figure 6.42. In this program variables Vdec and Vfrac store the integer and the fractional parts of the number respectively. The decimal part is then converted into a string using function LongToStr and leading blanks are removed. The parts of the fractional number are called ch1 and ch2. These are converted into characters by adding 48 (i.e., character “0”) and then displayed at the next cursor positions using the LCD command Lcd_Chr_Cp.
We could also calculate and display more accurate results by using floating point arithmetic, but since this uses huge amounts of memory it should be avoided if possible.