CSEP567 Lab 4: “LCD and ADC”

Objectives

The goal of this lab is to introduce how to program the microcontroller using C. In this lab you will learn the following:  

This lab assignment has 2 required sections and 1 optional section.

Suggested Reading

LCD Information

The LCD which you will be using has many advanced functions (see the datasheet for a complete explanation), but you will only be concerned with the following two:

  1. Reset and clear the display.
  2. Write characters to the display.

We are using a LCD with a display area of 2 rows by 16 columns which gives a total of 32 characters that can be displayed at once.

The pin layout of the LCD follows:

Pin

Name

Function

1

GND

0 V

2

Vdd

5 V

3

Vo

1 V

4

RS

High: Data input

Low: Instruction input

5

R/W

High: Read from LCD

Low: Write to LCD

6

E

Enable the LCD

7

DB0

Data bus

8

DB1

9

DB2

10

DB3

11

DB4

12

DB5

13

DB6

14

DB7

 

Pins 1-3 are power supply connections and will be explained later. Pins 4-14 are signals that you must supply.  R/W specifies whether you are reading or writing the display: Since you will only be writing to the display, the R/W signal will always be 0. RS is used to determine whether you are sending a command or ASCII data to the display. E (enable) is used to provide a strobe that causes the operation to be executed.  The enable E is really a clock signal for the LCD that you must generate: the LCD reads the signals being placed on its pins and commits a new character or command on the negative edge of E. (NOTE: negative edge means the signal is changing from 1 to 0, or Vcc to gnd) The data pins contain either an ASCII character code or a command code depending upon the value of RS. In Lab you will need to multiplex this data bus between the signals meant for the LCD and signals meant for the 7-segment LED.  

The following is a table with the codes for 5 of the commands that you need to execute for this assignment. The first four should be called in an intialization routine and executed in sequence on reset. Please check the datasheet for the timings needed. The last command is used to write a character to the display. You can look at the documentation (see the datasheet) if you would like to try out other commands.

Operation

RS

DB[7:0]

Clear Display

0

0000 0001

Function Set

0

0011 1000

Display On

0

0000 1100

Entry Mode Set

0

0000 0110

Write Character

1

DDDD DDDD

Suggested Steps

Section I. LCD

  1. Connect the LCD according to this schematic. Note that the LCD pins connect directly to the processor PORTC pins, not on the other side of the resistors. You will need to calculate what resistors you will need to generate 1V.
  2. Verify that everything is hooked up properly by using your two functions from the prelab to initialize and print characters to the LCD screen. 
  3. Next, include <stdio.h> in your code and near the top of main add the following line of code: "fdevopen(lcd_putchar, NULL, 0);"  This will cause stdout to be directed to the lcd_putchar function (from prelab) allowing printf's output to be directed to your LCD screen.
  4. Modify your code so that it multiplexs PORTC between the LCD screen and the 7-segment LED. To accomplish this take advantage of the fact that the LCD screen will only read input on the negative edge of E. By placing the needed data on PORTC for only a fraction of second and then restoring the 7-segment LED data as soon as it's done sending you should be able to use PORTC to control both devices. There might be a small amount of flicker but by executing the LCD commands quickly it should be miminal. NOTE: You need to be careful that another section of code does not update PORTC values when the LCD functions are sending data on PORTC. (Ask a member of the course staff if you are confused on how to multiplex)

Before moving to Section II demonstrate to a TA that the LCD screen is working. The LCD will hopefully provide a useful debugging tool for the rest of the labs that use the prototyping board.

Section II. ADC

  1. Implement a program that continually displays the analog value of the potentiometer on the two 7-segment LED displays. You should read the section in the datasheet on the Analog to Digital Converter to find out how to obtain the analog value. To increase accuracy use a large prescaler. You'll want to use the interrupts to tell you when the conversion is complete. Also note that the ADC has 10-bit resolution but only 8-bits are needed for the display, so you can throw away the 2 least significant bits. Note that the datasheet describes a nice way to get the 8 most significant bits.  

    Question 1: Does brighter light or dimmer light give you a higher analog value? What is happening to the resistance?

  2. Use a button to toggle between the system displaying 8-bit analog values from the potentiometer or the photoresistor.
  3. Demonstrate that your multiplexing of PORTC is working correctly by recording the value of the ADC every 10 seconds. Each line should display either "Light: %d\n" or "Pot: %d\n" (depending on which ADC is being read) and be followed by a new line to demonstrate your wrapping. NOTE: The 7-segment LEDs should be constantly updating.

Demonstrate Section II to a TA (see delieverables section).

Section III. Light Sensor (Optional, for fame and glory... no credit involved)

  1. Use the potentiometer and photoresistor to create an adjustable light sensor that will turn lights on when it becomes dark. The photoresistor will be used to monitor the current light level of the surrounding environment. The potentiometer will be used to adjust the level at which the sensor will trigger the lights to come on. This will allow the user to customize their home so the lights turn on and off at the desired darkness. Once the photoresistor reports that the level of darkness specified by the potentiometer has been reached, the ATmega16 should turn on the lights. (In this case the light is an LED attached to pin 21.) Once it becomes light enough the ATmega16 should turn off the LED.
  2. To determine the voltage difference between the potentiometer and photoresistor you should use an ADC differential channel. The potentiometer should be the positive differential input and the photoresistor should be the negative differential input. The ADC will return a signed number (in two’s complement) that represents the voltage difference between the two differential input channels. The two 7-segment displays should display this signed 8-bit value by using the tens digit decimal point to represent the negative sign.

NOTE: You might want to average some of the ADC values to prevent the light from flickering on and off. A weighted moving average might be a good idea for smoothing. Below is an example formula for a weighted moving average where a larger value for x will cause “new value” to have a smaller affect on the average.

average = ((previous average * (x -1)) + new value) / x

Deliverables

For all files turned in, the comments at the top of the file should contain:

  1. Demonstrate your light/potentiometer reader to a TA. Remember your code should do the following
    1. The display should be able to range from very close to 0 when the pot is turned all the way one way to very close to 0xff when the pot is turned the other way.
    2. The LCD screen should show whether the values being displayed are from the potentiometer or the photoresistor.
    3. It should be reasonably responsive to changes of the potentiometer or in the level of light.
    4. Your code should track the position the next character will be displayed on the LCD (2 rows, 16 columns) and automatically move the cursor as needed to the beginning/home position of the next line. When reaching the end of the second LCD line it should wrap to the beginning of the first line of the LCD. (NOTE: That if you do not move the cursor the LCD will type off the screen and you won't be able to see the text.)
    5. Your code should recognize '\n' and move the cursor the the appropriate line (wrapping).
    6. Your code should clear each line before writting to it.
  2. Turn in hardcopy of your commented C code and your answer to question 1.