EENG 383

In Lab 3 - Music Box

Requirements

Working in teams of two, read through the following lab activity and perform all the actions prescribed. You do not need to document bullet items. Make a record of your response to numbered items and turn them in a single copy as your teams solution on Canvas using the instructions posted there.

Include the names of both team members at the top of your solutions. Use complete English sentences when answering questions. If the answer to a question is a table or other piece of art (like an oscilloscope trace or a figure), then include a sentence explaining the piece of art. Only include your answers, do not include the question-text unless it is absolutely needed.

Objective

The objective of this lab is to introduce you to the MPLAB Code Configurator (MCC) and how to use delays to generate sounds.


External Hardware

Today you will write code that you can interact with through a button (input) and generate musical tones through the speaker (output). You should be familiar with the operation of the buttons from last week's lab. Since this lab is already jam packed with goodness, we will wait until next week's lab to explore the hardware on your development board that converts the low power output from the PIC into a high power signal to drive the speakers.

Internal Subsystem

This lab will use one of the GPIO pins as an output driving the speaker and two of the GPIO pins to read the push buttons.

In order to use the speaker you need to install a 2 pin jumper (shown below) over the pair of pins 5V (near the USB connector). Leave this jumper in place until you need 5v or want to measure the current consumed by the development board.


We will compare the delay generating paradigm used in last week's lab, having the processor idly execute NOP instructions to create delays, and timers. NOPs are useful in simple applications and where you need to create very brief delays. However, in order to generate more precise delays, or to allow the micrcontroller to perform other work while waiting for the delay to be over, you will need to learn to use timers. While you may question the benefit of the added complexity timers introduce into your code, I hope that you will soon realize that they represent one of the most powerful subsystems in a microcontroller.

Firmware Organization

A microcontroller by itself is not terribly interesting, being not much more than a slow-running processor. Microcontrollers derive their power from the subsystems they contain and the external devices these subsystems can control. In order to be able to interface to as many different external devices as possible, the computer engineers who design microcontrollers make the subsystems as flexible as possible. This means that there are potentially a great number of alternative configurations for each subsystem. When developing an embedded application that interfaces a microcontroller subsystem to an external device, one of the first tasks you must complete is configuring the subsystem.

In my experience subsystem configuration is a necessary task that can turn into a time consuming and potentially-frustrating challenge. Thankfully, the folks at Microchips developed the MPLAB Code Configurator (MCC) to address this challenge. Paraphrasing the text in the MPLAB® Code Configurator User’s Guide, MCC is a plug-in tool in MPLAB X which generates drivers (software) for controlling and driving subsystems based on the settings and selections made in the Graphical User Interface. The generated drivers can be used in your program.

Create new project

The first step to using MCC is to create a new project and launch MCC as described in the steps below.

Configure the PIC with MCC

You should use MCC for the remainder of the term for all future projects. Every project in this class will require you to configure the oscillator and I/O pins as shown in the steps below. Consult the figure below the text in case you have difficulty finding some of the selections described.

If you installed the plugin correctly, there should be a blue shield icon in the toolbar labeled “MCC”. This is the code configurator. Click the icon and hit “save” when given an option to save your configuration files. See the image below for assistance in locating buttons described in the following instructions.

Add source code

In addition to generating the code to configure the PIC, MCC generates a variety of useful function and definitions that you can call from inside your code. In this lab, I have written a simple program that uses some of these definitions. In the steps below, you will add this program to your project. Before running the inLab03.c program, take a moment to look at the structure of the files created by MCC and the utility functions and definitions contained in them. In the project manager window expand Header Files → MCC Generated File. Double click and open all the files in this folder. Use the contents of the files to answer the following questions.
  1. What three defined expressions are available for you to write values to the Speaker? Hint, these all manipulate the Latch and contain a set of parentheses.
  2. What defined expression can you call in your code to get the value of TOP_BUTTON? Hint, it's not TOP_BUTTON_PORT - we want a similar expression that has parenthesis.
  3. List all the functions that you can call to interact with timer 1.
In the project manager window expand Source Files → MCC Generated File. Double click and open mcc.c, pin_manager.c, and TMR1.c in this folder. Use the contents of these files to answer the following questions.
  1. What functions does the SYSTEM_Initialize call?
  2. How does the MCC TMR1_ReadTimer function form the 16-bit timer value from the two 8-bit timer 1 registers?
In the project manager window double click and open main.c. Use the contents of main.c to answer the following questions.
  1. List all the calls in main.c to definitions contained in the MCC Generated Header Files. To answer this question, look through all the "#define" statements in the Header Files generated by MCC. Write down any of these "#define" statements that you can find in main.c. For example, main.c calls TOP_BUTTON_GetValue() (from pin_manager.h) so this should be included as part of your answer. Also, all of the #define values are shown in light blue text. Note, some of these #defines are declared in main.c - do not include these, only ones declared in the MCC Generated Header Files.
  2. List all the calls in main.c to functions contained in the MCC Generated Source Files. To answer this question, look through all the functions declared in the Source Files generated by MCC. Write down any of these function declarations that you can find in main.c. For example, main.c calls TMR1_WriteTimer() (from tmr1.c) so this should be included as part of your answer.
  3. Given the configuration of the push buttons discussed in a previous lab, when will the instructions inside the while-loop on lines 44-45 be executed, when the top button is being pressed or unpressed?
  4. When will the instructions on lines 47,48 be executed, when the top button is pressed or when the button is released?

Firmware Operation

Your next step will be to download the firmware into the PIC, then run and observe the behavior of the program. Using MCC does not require you to change this process; so the following steps should be familiar. Setting up the oscilloscope probe for this experiments can be a bit tricky, the image below is one way you can accomplish.


Observe output

One of the primary reasons electrical engineers use oscilloscopes is to observe phenomena that are too fast and too small to be observed directly with something like a digital multimeter. In the following steps, you will use the oscilloscope to observe the signal, generated by your program, coming from RB5.
Ch1 probe RB5
Ch1 ground clip Dev board ground loop
Horizontal (scale) 1 ms
Ch1 (scale) 1V
Trigger type Edge
Trigger mode Auto
Trigger source 1
Trigger slope
Trigger level 1.5V
Make sure to:


  1. Include the screenshot (saved on a thumbdrive) of the 980Hz note waveform generated while pressing the top button.This will be the note that plays on the first button press. If you missed it, just press the top button a few more times to cycle back around. You can verify that you have the right note by measuring the frequency of your waveform ([Meas] → Add Meas → Type: Frequency → Source 1 → Add Measurement).
  2. Using the time per division information on the oscilloscope screen shot and the duration of the waveform (described in divisions), show your calculation for the period of the waveform on RB5. Invert the period to also determine the frequency. For example, if your oscilloscope was set to 250us/division and the waveform had a period of 4.6 divisions, then your answer would look like:
    Oscilloscope set to 250us/division
    The period of the RB5 waveform is 4.6 divisions
    
    	 250us      
    	-------- *  4.6 divisions = 1,150us	1/1,150us = 869Hz
    	division 
    

Firmware Experiments

Your program uses delays to generate the musical notes in a traditional western music scale. The code to generate notes using TOP_BUTTON is similar to this:
            while (TOP_BUTTON_GetValue() == 0) {            
                microSecondDelay(halfPeriod[i]);                
                SPEAKER_PIN_Toggle();
            } // end pressed button  
In order to generate frequencies that correspond to the notes in a traditional musical scale, you need to understand the mathematical relationship between a note and its frequency as described in the first paragraph of the Equal temperament wikipedia page. You will use an excel spreadsheet to compute the halfPeriods (from the code snippet above) of the notes A4 … D#6. Follow these steps to complete this task.
Index Note Freq (Hz) 3 sig figsPeriod (ms) 3 sig figs Half period (ms) 3 sig figs TMR1 cnts
0A4 440 2.2731.137 
1A#4     
2B4      
3C4      
4C#4     
5D4      
6D#4     
7E4      
8F4      
9F#4     
10G4      
11G#4     
12A5 880 1.1360.5682 
13A#5     
14B5      
15C5      
16C#5     
17D5      
18D#5     
19E5      
20F5      
21F#5     
22G5      
23G#5     
24A6      
25A#6     
26B6      
27C6      
28C#6     
29D6      
30D#6     
31Ultrasonic 31,000   
Your program also uses timer delays to generate the musical notes using BOTTOM_BUTTON is similar to this:
            while (BOTTOM_BUTTON_GetValue() == 0) { 
                TMR1_WriteTimer(0x10000 - halfPeriodTimer[i]);
                PIR1bits.TMR1IF = 0;
                while(TMR1_HasOverflowOccured() == false);
                SPEAKER_PIN_Toggle();
            } // end pressed button   

Please note that TMR1 operates identically to TMR0. That means that TMR1 counts up at Fosc/4. Since you configured Fosc = 64MHz, then TMR1 counts up 16,000,000 times a second.

In order to generate frequencies using timer 1 counts, you need to reinterpret the half periods in column E in terms of timer 1 counts. To do this let's start by writing an equation which converts a delay in milliseconds into 1:1 prescaled timer 1 counts.
  1. Write a dimensional analysis equation to convert a half period delay in milliseconds into 1:1 prescaled timer 1 counts. Do this using the following steps:
    • Write 16*106 clk over 1 second
    • Multiply this by the number of timer 1 counts per clock
    • Multiply this by the number of seconds per milliseconds
    • Multiply this by a variable X which represents the number of milliseconds in a half period.
    Please write out the dimensional analysis using the form we used in class and that used in your lecture notes.
Calculate the number of timer 1 counts for each note in your Excel spreadsheet using the following instructions:
  1. Export the completed spreadsheet as a PDF as the solution to this question. To accomplish this, complete the following steps.
    From Excel: File → Export → Create PDF/XPS Document. Save the file in your lab03 directory. In Word: Insert → Object → Adobe Acrobat Document
    Don't forget the last question below.
  2. Modify the program so that it plays the notes from any of the popular Kids songs using the noted from the table above. Demo the application to the lab instructor or TA.


Got a problem, try a solution

Issue Solution
Intermittent, crackle sound Install jumper over power input jumper 5V
Speaker makes sound but oscilloscope is not showing a waveform. Disconnect and then reconnect your oscilloscope probe
Speaker makes no sound and RB5 produces no square wave when button is pressed. Configure RB5 as an output in pin manager and make sure that you have installed a jumper wire from RB5 to AMPin.
Speaker makes no sound and oscilloscope probe of screw terminals shows a square wave. Your LM4862 chip is in backwards.
You are making changes to the program, but they do not seems to be affecting your program the way you expect. You have two projects open
You are getting a BUILD ERROR (main.c already defined) when compiling your program You have two .c files in your project, both have void main(void) { defined in them.