Setting up Analog I/O and Unidirectional EUSART on the PIC18F47Q10

Introduction

Many sensors have an analog output that must be digitized using an Analog to Digital converter (ADC) in order to use them in a microcontroller. The PIC’s ADC subsystem is the peripheral used to read analog values and convert it into a digital number for use in your program. It can be configured in a variety of ways. In this assignment, you will create an ADC subsystem and program your microcontroller to transmit the result of reading an analog voltage measured at an input pin, using the ADC subsystem in one of its simplest configurations.

Likewise, PWM signals are often used to control a variety of actuators (e.g., servo motors), and, because they provide a proportional time-based signal, can be used in certain circumstances, as an analog output from a microcontroller. In this assignment, you will also program your microcontroller to generate a PWM signal using the measured ADC value, and demonstrate modifying the output of the PWM signal in two key ways.

The goal of this assignment is to introduce you to the MPLAB® X IDE, and to verify that you can create a project, add peripherals (ADC, PWM, EUSART), and use them together. By the end of this assignment you should be able to demonstrate proficiency in:

  1. Configuring your microcontroller to send data across a virtual COM port to your PC.
  2. Measuring an analog voltage using an analog to digital converter
  3. Outputting the measured ADC value over EUSART
  4. Converting an ADC value to Voltage and outputting the result over EUSART
  5. Changing a pulse-width modulation (PWM) signal
    1. With a specific duty cycle from your microcontroller output pin.
    2. By changing the frequency of the cycle itself

Resources

Parts Needed

Item Quantity Value(s)
PIC18F47Q10 Curiosity Nano 1
Breadboard 1
Resistors 1 TBD by student
LED 1 Any color
Jumper wires Several

Instructions

You may use your Nano board or a breadboard with your microcontroller on it.

  1. Using the Hardware User Guide and lessons learned last semester with connecting to the PSoC®, study the following critical information and concepts:
Critical Information and Concepts Importance
a. The name of the virtual COM port that communicates over the Curiosity Nano’s USB to your computer. Needed in order to connect PuTTY to the Curiosity Nano
b. Which EUSART subsystem connects to it Needed to determine which EUSART port to connect the PIC to in order to communicate with the debugger and computer
c. Which specific pins are used for receive and transmit on the PIC Needed to assign the correct pins to the EUSART component
d. How much current can a digital I/O pin safely source or sink? (Hint: See the PIC18F47Q10 Datasheet) Needed to match the current needs of external loads (e.g., LEDs) with the IC and determine whether you need interface circuitry (e.g., a transistor)
e. Which pin of the Curiosity Nano board outputs the regulated power used by the “target” (the PIC18F47Q10) Needed to know where you can access power and ground on the Curiosity Nano board
f. Which pins of the Curiosity Nano connect to ground?
g. How many bits wide is the result of an ADC read?
h. How many bits wide is the PWM timer register?
Needed to read, interpret, and write data to and from the ADC and PWM peripherals. Can be found in the PIC18F47Q10 Datasheet
i. How to shift bits of a number or variable (needed to manipulate data in an 8-bit variable)
j. How to mask bits of a number or variable (needed to read or write specific bits in an 8-bit variable)
k. How to cast a variable as a different data type (needed to convert variables from one data type to another)
Needed to manipulate data in variables. Can be found in a C programming reference, such as the GNU C Reference Manual
  1. Open the Curiosity Nano box and the two antistatic bags inside. Solder the headers into the PCB so that the long side can be plugged into a breadboard and the short side goes through the PCB and can be soldered on the top.

  2. Follow the instructions in the Quick Start section of the Hardware User Guide to download and install the MPLAB® X IDE (including IPE and 8 bit MCU support), XC8 compiler, and MPLAB® Code Configurator (MCC). Note: The free compiler license is sufficient for this course.

  3. Open MPLAB® X IDE and plug the Curiosity Nano board into the USB port of your computer

  4. In MPLAB X, create a new project for the PIC18F47Q10. Ensure the curiosity nano is connected over usb before starting project setup so you can select it as the programming “tool” during setup.

  5. Open MCC, and select the default file location when prompted.

    Please use MCC Classic. We can support it better, it has more advanced configuration options, but is also still relatively easy to use.

  6. Open the project in MPLAB® X and MCC, then add and configure the following peripherals:

    1. System Module:
      1. select the HFINTOSC (high frequency internal oscillator) at 4 MHz.
      2. Keep the clock divisions at 4.
      3. disable the Watchdog timer
    2. EUSARTX
      1. Add and configure a new EUSART peripheral (the one that connects to USB). Make sure you check the “connect to stdio” box.
    3. ADCC
      1. Ensure right result alignment (this means the data is right-justified in the result register)
      2. Do not select continuous operation
      3. Keep all other defaults
    4. PWMX
      1. Note the Timer Source (you will need this for the next step)
      2. Set the initial duty cycle to 50%
      3. Keep all other defaults
    5. TMRX, where X is a specific timer that must be matched to the PWM subsystem selected.
      1. Use the FOSC/4 setting (you will get an error otherwise).
      2. Use the highest prescaling possible (to ensure the timer counts slowly)
      3. Set the timer period to the maximum possible (to further slow down the count so that the LED blinks slowly)
      4. Keep all other defaults

    Pay attention to and follow all instructions provided by the MCC’s warnings and errors in the Notifications [MCC] window

  7. Open up the pin manager grid

    1. Ensure that RX and TX are mapped to the correct pins (as you found it from the HW User Guide’s pinout section in the previous step).
    2. Select an analog input pin (ANx)
    3. Select a pin that connects to PWMX
  8. In the Pin settings(in the resources window), ensure that

    1. your RX pin is set to a digital input (leave the analog option unchecked)
    2. your TX pin is set to a digital output (leave the analog option unchecked)
    3. the second TX pin (for the external LED) is set to a digital output (leave the analog option unchecked)
    4. the PWMX pin is set as a digital output (leave “analog” unchecked)
    5. that the ADCX pin is marked as an analog input.
  9. Generate the MCC configuration

  10. Open EUSARTX.h (where “X” is the correct EUSART peripheral) in the MCC-generated header files within the project explorer. Read through this document, Identify each function and determine what the purpose of each is. Then find the function that initializes this EUSART subsystem and note it.

  11. Open up ADCX.h

    1. Find the function that permits you read a single ADC value (conversion). Copy the example code into main.c

      1. Hint: Pay attention to the number of bits in adc_result_t in the typedef statement. This will be important later.

      2. Note: The example code has an error. The following line:

        adcX_channel_t convertedValue;
        

        should be as follows instead:

        adc_result_t convertedValue;
        
    2. Find the declared constant for the ADC input pin you have configured (hint: check the Pin Module). Supply this value as the input to the ADC single-read function.

    3. You will need to define a new variable to use the output of this function. Refer to the commented out example code to determine the appropriate data type for the variable.

  12. Open up PWMX.h

    1. Find the function that permits you to set the duty cycle. Copy the example code into main.c
    2. You will need to define a new variable to use the output of this function. Refer to the commented out example code to determine the appropriate datatype.
  13. Open up TMRX.h

    1. Find the function that permits you to set the period register. Copy the example code into main.c but leave it commented out for now
    2. You will need to define a new variable to use the output of this function. Refer to the commented out example code to determine the appropriate datatype. Add a new line of code for using the ADC value you read and converted previously to change the PWM duty cycle.
  14. Now tie these new functions together into your main.c:

    1. Add a new line of code to read a single value from the ADC and store it in a variable of the correct type. Refer to the adc subsystem header file generated by MCC to find the correct data type.

    2. Next, add a new line of code to output the data stored in that variable to EUSART using printf(). Make sure to add carriage return and newline characters to clean up your transmission so that each new ADC value is output on a new line in Putty.

      Hint: Remember that X bit variables will have values between 0 and 2^X^-1. If you are printing numbers outside of that range then something is incorrect with your conversion. See Microchip’s documentation on printf() for more information.

    3. Next, add a new variable with type float and use it to translate the integer ADC value to a decimal value that represents the voltage read on the ADC pin. Output that floating point value using the printf() function and the format specifier section of the printf()documentation linked in the previous step and as seen in the MPLABX tutorial. Your data should print on two lines, e.g.:

      ADC value: 255
      ADC voltage: 3.300
      

      NOTE: This may require a brush up on data types and converting or type casting from int to float in C.

    4. Add a new line of code for using the ADC value you read and converted previously to change the PWM duty cycle. This is the raw ADC value before you converted it again to voltage.

      Context: Changing the duty cycle changes the percentage of the time a square wave is low or high. Variable duty cycles are often used for driving RC Servos or -- in conjunction with a low pass filter -- for approximating a simple and low-fidelity digital to analog converter(DAC).

      Ensure you are converting the X-bit ADC value to a properly-formatted Y-bit duty cycle value. (Though the functions that operate on these two registers accept 16-bit variables, they only use the least significant / bottom X and Y bits of each 16-bit variable). The information about the size of X and Y was found by you in the first steps of this assignment.

      More Context: The X-bit resolution(see PIC18F47Q10 Datasheet) ADC result is stored in a 16-bit variable of type adc_result_t, which is wider (more bits) than the resolution of the ADC result. Furthermore, the PWM duty cycle register holds fewer bits than the resolution of the ADC. Thus, we want to transfer the most significant bits of the ADC’s reading into the PWM’s duty cycle register. The least significant bits of the ADC represent such a small difference in the final result that they can be truncated (cut off).

      Write a line of code that uses a C bit shifting operator to shift the ADC result so that the most significant 8 bits of the ADC’s output are used as an input to the PWM subsystem’s duty cycle update function (look in the PWM header file). Be sure to “cast” this variable into the correct type declared by that function.\

      After shifting, the lower 8 bits of your adc_result_t variable should look like this (where x is the number of resolution bits for the ADC):

ADCx-1 ADCx-2 ADCx-3 ADCx-4 ADCx-5 ADCx-6 ADCx-7 ADCx-8
  1. Download the project to the target. This can be done one of two ways
    1. Using the download button (ensure you are connected to the Curiosity Nano board rather than the simulator, and that you have selected the Curiosity Nano as the programming “tool”.)
    2. Copying the .hex file from project-name/dist/production/project-name.hex to the “Curiosity” drive in file explorer.
  2. Add a potentiometer to your system
    1. Connect the wiper pin of a potentiometer to the analog input pin
    2. Connect the other two pins of the potentiometer to the Curiosity Nano’s regulated 3.3V power and ground (see the power supply section of the Hardware User Guide for more information, and verify with your DMM prior to connecting the potentiometer).
  3. Add an external LED & resistor to the PWM output pin so that the LED safely turns on whenever the PWM output is high. (safely means that neither the LED nor the microcontroller pin burns out. Select an appropriate current-limiting resistor based on the LED specifications and the PIC18F47Q10 maximum pin current in the Datasheet)
  4. Demonstrate that the voltage read by the ADC can be used to alter the duty cycle of the PWM signal.

And that’s it!