EE 109 - Spring 2025 Introduction to Embedded Systems

Lab 8

Hardware Datapath Components

Honor Statement

This is an individual assignment. The code you write, use for the demo and submit should be wholly your own and not produced by working in teams or using, in part or in whole, code written by someone else (found online, from a fellow student, acquaintance, etc.). You will be asked to verify this when you submit your code on Vocareum by signing your name in the honor.txt file on Vocareum. Penalties for violation include a 0 on the assignment and a potential further deduction or referral to Student Judicial Affairs.

Introduction

In this lab exercise you will use the ADC code you wrote in Lab 7 to interface the microcontroller to a potentiometer and to the buttons on the LCD module. These will be used as inputs to a moderately complex digital circuit to control the color and brightness of an LED. The circuit utilizes some of the hardware functional components we have studied in the lectures. This assignment will use a three-color LED (red, green and blue) where the color to be illuminated is selected using the LEFT and RIGHT buttons on the LCD. When these buttons are pressed the LCD will indicate which LED color is on and that color will light up. The brightness of the each LED color has two modes that are selected by pressing the UP or DOWN buttons. If the DOWN button has been pressed the brightness of the LED is determined by a pulse-width modulation (PWM) signal that controlled by the position of the potentiometer. So as you twist/rotate the potentiometer with your screwdriver, the brightness of the LED should increase or decrease. If the UP button has been pressed, then that LED color is set to full brightness and can not be adjusted by the potentiometer.

This lab uses several new components that were not provided as part of your lab kit at the start of the semester but were included in the bag of parts containing the servo motor that was handed out for Lab 7.

To see a short video demonstrating the operation of lab, click here.

For a copy of the Lab 8 grading sheet, click here.

Overview of Circuit

A block diagram of the circuit you will be building is shown below. It consist of five components:

In the sections below we will describe the circuit in more detail including showing how to wire most of it together.

Take care when you start wiring. Some of your demo points are for using APPROPRIATE colors (red = 5V, black = GND) and neatness.

Getting Started

Set up the Lab 8 assignment the same as has been done previously by creating a lab8 folder in your ee109 folder.

The Lab 8 program will be used during the installation of the hardware components to confirm that the components are working correctly. Because of this it’s necessary to get it running and downloaded to your Arduino even though the hardware hasn’t been installed yet.

If you look at the lab8.c file you will see that much of the code has been provided for you. At the start of the program add code to do the following:

Once this has been done you are ready to move on to Task 1 and start adding additional code to interface with some of the hardware.

Task 1: Write the ADC routines

The Arduino’s analog-to-digital converter (ADC) module is used in this lab to adjust the width of the PWM signal going to the LEDs, and also to determine if one of the buttons on the LCD has been pressed.

Writing the code to operate the ADC module was one of the tasks in Lab 7 and you should be able to copy the adc.c and adc.h files from your lab7 folder to the lab8 folder. If you did not complete Lab 7 and do not have a functional adc.c file you will have to go complete this task as described in the writeup for Lab 7 before you can move on to the rest of Lab 8.

Information on using the ADC module is available in a lecture slide set. A more in-depth review of this material is provided in a separate document “Using the Atmel ATmega328P Analog to Digital Conversion Module available on the class web site. Refer to any of these resources for information on configuring the various registers in the module and how to do the conversions.

Task 2: Determine the LCD buttons values

As part of Lab 7 you should have determined what value is returned by the ADC for each of the five buttons on the LCD. These values will have to be edited into the lab8.c files. If you did not complete Lab 7 you will have to do Task 2 in Lab 7 to determine these values.

Task 3: Install and Test the Potentiometer

The first part of the circuit uses a potentiomter to adjust the duty cycle of a PWM signal generated by one of the Arduino TIMER modules in the same manner as it was used in Lab 7. In this lab there will be several other components installed on the breadboard so we recommend that the potentiometer be installed near one end of the breadboard, perhaps between rows 5 and 10 of the breadboard. If you have to move the potentiometer, make sure to install it properly so the three pins are in three different 5-hole connection strips as was done in Lab 7.

As was done in Lab 7, make the following connections to the potentiometer.

Once the potentiometer is installed it’s highly recommended that you confirm that you have the potentiometer connected properly by using the DMM as was done in Lab 7. Check that the voltage on the slider pin can be changed by rotating the control. The DMM should show +5V when rotated fully in one direction and 0 when rotated to the other limit.

A second test of the potentiometer using the ADC is also recommended at this point. This will confirm that the voltage can be converted by the ADC into a number between 0 and 255. Your lab8.c file has a while(1) loop for testing the ADC. Flash the new code to your Arduino, and then try rotating the potentiometer back and forth.

The program should be displaying the numerical values of its conversions of the voltage on channel 1, and these should be close to 0 at one end of the rotation and close to 255 at the other. If you are not seeing this, you will need to fix the problem before using the potentiometer and ADC code in the next task.

NOTE: The while(1) loop that was used for Task 3 can now be deleted or commented out in your lab8.c file. The while(1) loop that is below that section of the file is the code that will do the rest of the lab assignment.

Task 4: Generate the PWM Signal

The next step is to write code to allow the digital value converted from the potentiometer analog input to control the duty cycle of a PWM signal generated by one of the TIMER modules. For this task we have to use the 8-bit TIMER2 module since it is the only one that has a PWM output that is accessible when the LCD is attached to the Arduino.

As was done in the Lab 7 where you used TIMER2 to control the position of the servo motor, TIMER2 will be used in the “Fast PWM” mode where it counts continuously from 0 to 255 and then starts over. At the start of the pulse period (count = 0) the OC2A output signal, which appears on Arduino port D11 (Port B, pin 3), will go to the high state to start the pulse. Register “OCR2A” is used to store a value that determines the pulse width by telling the timer when to terminate the pulse. During each pulse period, the timer counts up incrementing the count value, and when it reaches the value in OCR2A the output signal goes back to zero while the timer continues to count up to 255. The counter then resets back to zero and the process is repeated for the next pulse.

To control the brightness of the LED, we would like to generate a PWM signal with a period of 1ms or as close as possible to that. This means TIMER2 must be clocked at a rate that makes it count 256 times in 1ms, or about 3.9μs per count. The 16mHz Arduino clock goes through about 62 clock cycles ever 3.9μs which is too fast. If we use a prescalar of 64 this slows the clock for TIMER2 down to 250kHz. At this rate it will do 256 counts in 1.024ms which is close enough.

The code you wrote in Lab 7 to initialize TIMER2 can be reused here, but make sure to change the line that sets the prescalar so it’s using a factor of 64. The CS22, CS21 and CS20 bits in the TCCR2B register should be set to 100 for a prescalar value of 64. You also don’t need TIMER2 to generate any interrupts so make sure to NOT enable TIMER’s overflow interrupts.

As was done in Lab 7, the width of the PWM signal is controlled by the value stored in the OCR2A register. For this lab, this is the value returned by the analog-to-digital conversion of the voltage from the potentiometer. In the main loop of your code, after getting the converted value, simply copy it to the OCR2A register. This way every time the potentiometer is varied, the ADC will produce a different value and this will change the PWM signal accordingly.

Once you have made these change to the code, download it to the Arduino. To see if it’s working, connect a scope proble to the PB3 (D11) output of the Arduino and try rotating the potentiometer. It should change the duty cycle of the PWM signal from close to 0% to being 100%

Checkpoint: Show the PWM signal on the scope to one of the teaching staff to record that you have the checkpoint task completed for this lab. Demonstrate that turning the potentiometer adjusts the duty cycle of the PWM signal across its full range.

The Circuit for Controlling the LEDs

Note: The following is a description of the LED control circuit. Don’t start wiring the circuit until you have finished reading this section and have an understanding of how it works, and then move on to Task 5 below to do the wiring.

The main part of the Lab 8 circuit contains the circuitry to control which LED is affected by adjusting the PWM signal, and also provides the ability to force an LED to full brightness. The schematic diagram is shown below

74LS164 Shift Register

The shift register is controlled by two signals from the Arduino.

The shift register stores five bits that control the multiplexer and the decoder.

Note that you can not load the individual bits in the shift register. Each time your code needs to change any of the these bits, it must reload all five bits in the shift register.

74LS139 Dual 2-to-4 Decoder/Demultiplexer

The decoder/demultiplexer is used to determine which LED color is illuminated by the PWM signal. This IC contains two independent 2-to-4 decoders/demultiplexers. This IC is called a “decoder/demultiplexer” since it can serve either function depending on how it is used. In this lab assignment we will use one of them as a “demultiplexer” (reverse multiplexer).

This demultiplexer has active low outputs meaning that the selected output will be in the 0 state and all the other outputs will be in the 1 state. This is the opposite from the decoders that were discussed in the lecture where the selected output was a 1 and all the others were 0. The enable input (EN) is also an active low input so when EN is a 1 this is the disabled state and all the outputs are 1’s. We can operate the device as a demultiplexer by connecting the input signal (the PWM signal from the mux) to the EN enable input.

When used in this manner the PWM signal is effectively connected to whichever output is selected by the two selector bits, essentially a “demultiplexing” operation.

Brightness Control Gates

The Y0, Y1 and Y2 outputs from the 74LS139 are each connected to one input of three AND gates which are actually NAND gates with a NOT gate on the output to produce the equivalent of an AND operation. The other input of each gate comes from the 3 bits stored in the shift register in bits Q2, Q3 and Q4

The output of the NOT gates are connected through current limiting resistors to the three colors of the RGB LED. When the gate output is in the 0 state, that LED color will illuminate.

Installing the ICs on the Breadboard

In addition to the potentiomer you just installed, the circuit for Lab 8 uses four integrated circuits that will have to be installed on the breadboard and wired correctly. One of the ICs (74HCT04) was in the original set of components provided at the start of the semester. The other three should have been in the components handed out for Lab 7.

Note: Some of the ICs supplied are from the “74LS” family of ICs, and some may be from the newer “74HCT” family. ICs from these two familiies are compatible and can be connected together. In the discussion or diagrams below it may mention a 74LS139 but if yours is a 74HCT139 it works exactly the same.

Before installing them on the breadboard make sure that you can identify the proper way to orient the IC. All ICs have a marking on the package to identify pin number 1 as shown below.

Image

There are numerous ways the ICs can be positioned on the breadboard. However the length of the wiring connections that will have to be made can be reduced significantly by careful selection of where to install the ICs. To simplify the wiring connections we strongly recommend that you install the ICs in the positions shown below.

The rows of holes on the breadboard are numbered from 1 to 63 and we recommend installing the ICs so that pin 1 of each IC is in the following positions:

The potentiometer can be installed in the space between rows 1 and 10, and the space in rows 51 to 63 will be used for the multicolor LED and associated resistors.

This circuit requires that many of the IC pins be connected to power or ground. To greatly reduce the length of this wiring we strongly recommend installing two wires as shown in the diagram above the that connect the ground bus along the bottom of the board to the ground bus along the top, and similarly for connecting the two power buses together. This will allow you to connect the IC pins to power or ground with very short pieces of wire.

Task 5: Build the Shift Register, Decoder and AND Gate Circuit

In this task we will build the part of the circuit with the shift register, decoder, NAND and NOT gates. The pinout diagrams for the shift register and decoder are shown above. The diagram for the NAND and NOT gates are below.

Image

This completes the installation and wiring of the four integrated circuits. Make sure the wiring is neatly done and the wires are not excessively longer than needed to go between two points.

Task 6: Install the RGB LED

The final component to install on the breadboard is a multicolor LED. The LED is included in the same bag of parts from Lab 7 that contained the four ICs used above. The LED contains three separate LED elements inside it, one glows red, one glows green and the third glows blue, which leads to them being called “RGB LEDs”. The three LEDs inside it have separate cathode (lower voltage) leads, but their anode leads, the one that goes to the higher voltage, are connected together so it is referred to as a “common anode” device. On the package, the common anode lead can be identified since it is longer than the other three. When wiring up an RGB LED, all three elements need to have separate current limiting resistors as shown below.

It is recommended that you use the 240Ω resistors from your parts bag for the red and blue LEDs, and use one of the 680Ω resistor for the green LED.

Do the following steps to install the RGB LED.

Task 7: Finishing the Program

The lab8.c file provided for you contains several parts of the program that are already written. All the code for reading the button presses using the ADC and updating the LCD screen is provided and should not have to be modified. This part of the program modifies the variables “color” to have the values 0, 1 or 2, and modifies the elements of the “level” array to be either 0 or 1. Whenever any of these variables are changed, the new values must be transmitted to the shift register using two functions that you will have to write (the function skeletons are in the lab8.c file).

Whenever shift_load is called it must transfer all 5 bits (2 for the demux, 3 for the brightness) to the shift register, so it should make five calls to the shift1bit function. The shift_load function must also send the bits in the right order so they end up in the correct positions in the register after all five bits have been clocked into the register.

Write the code for the shift1bit and shift_load functions and you can then test the program to see if it works correctly. Below are some things to test.

If it is not working correctly, try checking the items below using the scope to observe various signals.

Results

When your program is running you should be able to confirm the following

Once you have the assignment working demonstrate it to one of the instructors. The answers to the review questions below should be edited into the Lab8_Answers.txt file. The Lab8_Answers.txt file and all source code (lab8.c, lcd.c, lcd.h, adc.c, adc.h and Makefile) must be uploaded to the Vocareum web site by the due date. See the Assignments page of the class web site for a link for uploading.

Please make sure to save all the parts used in this lab in your project box. These may be needed in the semester project. We suggest also saving all the pieces of wire you cut and stripped since those will be useful in later labs.

Review Questions

Answer the following questions and submit them in a separate text file (“Lab8_Answers.txt”) along with your source code.

  1. We would like to add a feature where if the Select button is pressed on the LCD, it turns the LED off completely, and then turns it back on when Select is pressed again. Explain how this could be done without having to make any changes to the wiring of the circuit .

  2. When TIMER2 is counting, the count value is kept in the TCNT2 register and is constantly being compared for equality (and only equality) to the values in the OCR2A register to determine when to terminate the PWM pulse. Suppose at some point your program adjusts the PWM width by changing the OCR2A register, and the new OCR2A value is lower than the value that is currently in the TCNT2 register. What will happen to the output signal during this pulse period?