# Cool Cap Engineer

## Implementing PWM On PIC18F Microcontroller

PWM output with 20% duty cycle.

# What is PWM?

As you guys know, microcontrollers, FPGAs, and other embedded processors can only output a high or low signal based on the power supplied to it. In other words, embedded processors cannot output a variety of voltages. Despite this, we have the processor “pretend” to output different voltages using a series of pulses and varying the width of the pulses. The technique of varying the width of a series of pulses is called Pulse Width Modulation (PWM).

The picture above shows an example of a simple pulse train.  The time it takes for each pulse to start again is referred as its period (Ts).  In each pulse train, the pulse is on for a certain amount of time before turning off. The percentage which the pulse’s on time compared to its time off is called the duty cycle.  Duty Cycle is expressed as…

$D=\frac{T_{on}}{T_{on}+T_{off}}$

# PIC18F And PWM

As you’re already aware of, all microcontrollers feature a set number of PWM pins. But what pins are specifically designed for PWM? When reading your PIC18F datasheet, look for pins that have CCP (compare capture pwm) labeled. So let’s look at a picture featuring the PIC18F4553

As you see in the picture, RC1, RC2 and RB3 can be configured as PWM pins.

# PWM Calculations

So there are three crucial registers you must take in account for PWM: PR2, and CCPRXL:CCPXCON[5:4]. Configuring the PR2 register, will allow you to configure the PWM period while selecting a proper the value for CCPRXL:CCPXCON[5:4] will allow you to choose the right duty cycle. For choosing the right value for the PR2 register, use the following equation…

$PR2=\frac{PWM Period}{4*T_{osc}*TMR Prescale Value}-1$

Keep in mind that Tosc is the the inverse of the frequency that your microcontroller is running at. Also, we will use a prescale of 16 as we will use this in the upcoming code example. For CCPRXL:CCPXCON[5:4], we will use the following equation…

$CCPRXL:CCPXCON[5:4]=\frac{PWM Duty Cycle}{T_{osc}*TMR Prescale}$

CCPRXL:CCPXCON[5:4] is a 10 bit number. To make things easier on you guys, make sure you convert your number to a 10 bit binary number. After you convert the number to a binary number, set your CCPRXL register to the first 8 MSB numbers. Finally, take the last 2 LSB and you use it for your CCPXCON[5:4].

# PWM Coding Procedure

Now that I talked about the calculations, let’s talk about how to code your PIC18F microcontroller to use PWM. For this tutorial, we will use the PIC18F4553’s  CCP1 pin, set the PWM period at 1KHZ, a time prescale of 16, a clock frequency of 8*10^6 and a 50% duty cycle.Parts of the final code can be found in my Beginner’s Guide To PIC18F Microcontroller.

First we need to configure the CCP1 pin as an output pin,which is RC2.To do this we set the TRISCbits.RC2 to 0 and PORTCbits.RC2 to 0.

TRISCbits.RC2=0;
PORTCbits.RC2=0;


Now, we need to choose a value for PR2 register. Here is my calculation for PR2.
$PR2=\frac{10^{-3}}{4*16*\frac{1}{8*10^{6}}}-1=124$
Now that we found the number, let’s convert it to a binary number and use it.

PR2 = 0b1111011;

PWM uses timer2 to work. So we need to not only turn on timer2, but we must set the time scale to 16. This can be done by properly configuring T2CON by setting T2CON’s TMR2ON to 1, and T2CKPS1 to 1.

T2CON = 0b00000111 ;

CCPR1L:CCP1CON[5:4] is the last thing to compute.
$CCPR1L:CCP1CON[5:4]=\frac{\frac{1}{10^{3}}*.5}{\frac{1}{8*10^{6}}*16}=250$
When we convert 250 to its binary value, we get 0011111010. However, we take the first 8 MSB for CCPR1L and the last 2 LSB for CCP1CON bit 5 and CCP1CON bit 4.

CCPR1L = 0b00111110;
CCP1CON = 0b00101100;


Since you guys been so swell, here’s the final code for this example.

#include <p18f4553.h>
#include <stdio.h>
#include <stdlib.h>
#include <usart.h>
#include <delays.h>
#include <portb.h>

#pragma config FOSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config PWRT = ON
#pragma config DEBUG=OFF

int main(void)
{
TRISCbits.RC2=0;
PORTCbits.RC2=0;
PR2 = 0b01111100 ;
T2CON = 0b00000111 ;
CCPR1L = 0b00111110;
CCP1CON = 0b00101100;

while(1);
}


## Tutorials: USART Communication For PIC18 Microcontroller

In my last post, I mentioned two awesome devices I’ve been messing around with lately. The cool thing about those devices is that it only needed one actual pin from the PIC microcontroller to properly work. This pin is one of the pins needed to achieve proper USART communication. Today’s tutorial will serve as a guide in order to achieve proper USART communication. Although I mentioned that USART is used to communicate with the devices I mentioned in the last post, today’s focus will be on achieving communication between PIC18F2550 and the computer using USART.

Circuity
USART (Universal Synchronous Asynchronous Receiver Transmitter)/ UART (Universal Asynchronous Receiver Transmitter) requires only two pins from any microcontroller to send and receive serial data: TX and RX. You can properly guess that TX is the pin which the microcontroller data is transmitted through, and RX is responsible for data received by the microcontroller. The figure below shows the TX and RX pins on the PIC18F2550.

Keep in mind; we need one more device to have the PIC18F2550 communicate with the computer. If you have an old computer, then you could use a MAX232 and connect it directly to the serial port of that computer. For this tutorial, we’re going to use a laptop to talk to the PIC. In order to do this, we’re going to use a FTDI to USB board from Sparkfun. We’re just going to use 4 pins of the FTDI to USB board: VCC, GND, TX and RX. Look at the figure below to learn how to set up the circuit. Please note that JP2 is connected to the PICKIT3.

Code
Now, create a new project in MPLab X, create a new C file, and code and paste the following code. If you forgot how to create a project in MPlab X, visit my tutorial on starting with PIC18 microcontrollers.

#include <p18f4553.h>
#include <delays.h>
#include <portb.h>
#include <usart.h>
#include <stdio.h>
#include <stdlib.h>

/*	PIC Configuratings */
#pragma config OSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config PWRT = ON
#pragma config DEBUG= OFF

/* UART Global variables */
char message;						//	Used for receiving commands from the computer

void main(void)
{
//	Set all of PORTC as outputs. TX and RX must be set as outputs first
TRISC=0x00;

//	Configure UART
OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE &USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 10);
Delay1KTCYx(4);
while(1)
{
while(!DataRdyUSART());
putcUSART(message);
Delay1KTCYx(4);
}
}


So open a Serial Terminal program. For this tutorial, I will use the Arduino IDE. Open the serial monitor in the Arduino IDE and set the baudrate to 115200. Finally, type a single character and hit send. You should see the same character you entered appear in the window.

Make sure you enter the right baudrate. If you do not enter the correct baudrate, you will lose data. The figure below shows what happens if we set the serial program to 9600 baud rate even though the PIC is set to a baud rate of 115200.

But how do you know if you set the USART to the right baud rate? Let’s look at the following piece of code.

OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE &USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 10);


As you can tell by the name, this is responsible for setting up the USART on the PIC. We’re going to look at the last two parameters of this command. The last two parameters correspond to the baudrate of the USART. USART_BRGH_HIGH sets the USART to a high baudrate, but we can set it to a low baudrate by replacing USART_BRGH_HIGH with USART_BRGH_LOW. The final parameter is a spbrg value. Although there are a set of equations you can use to find this value, as long as you’re using a 1Mhz, 2Mhz, 4Mhz, 10Mhz, 20Mhz, or 40Mhz crystal, you can find the SPBRG value in the datasheet. The figure below shows where we can find the spbrg value.

## Tutorials: Beginner’s Guide To PIC18 Microcontrollers

Starting today, I will focus on tutorials for  Microchip’s PIC18F series microcontrollers. Why am I shifting my focus from Atmega’s to PIC18F microcontrollers? As I stated in the first post of the N64 emulator controller, which is now Pygames Controller, I spent a semester at RPI learning how to use these microcontrollers and completely forgot how to use Atmegas. Not to mention, a lot of PIC microcontrollers are used for more commercial applications than Atmegas. If I remember correctly, Atmegas are mostly used for automotive applications while PICs are used for more commercial devices (e.g. medical devices). But enough about that! Let’s talk about how to start your first PIC18 microcontroller project.

# Necessary Parts

1. 1x PIC18F4553
2. 2x 22pf capacitors
3. 1 20Mhz crystal
4. 1 PICKIT 3 programmer
1. It’s highly recommended that you read this user guide for the programmer.
4. Lots of wire
5. 1x 330ohm resistor
6. 1x LED (any color)
7. 1x 10k resistor

Here’s the schematic of the circuit. Although the picture shows a PIC18F4455, they have the same pinout

# Necessary Software

Under the C18 Complier link, select MPlab C for PIC18.So once you guys install the necessary software, follow the next steps for setting up your project with MPlab X. First select file->New Project. Select Standalone project and hit next.

Type in “PIC18F4553” under Devices drop in menu. Hit next.

Select PICKit3 under tools. Press next.

Select C18 as your complier. Hit next.

Now we have create a project name and directory. Normally the project location and folder will be placed under my documents. Before this tutorial, I set the project location under my PIC folder. Remember to select “Set as main project.” This will save you the frustration later on. Finally hit finish.

Now we have to create a main file. Right click on Source files and select New-> C Main file. Type in main.c and hit finish.

Finally copy and paste this code into your main.c

#include &lt;p18f4553.h&gt;
#include &lt;delays.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

/*	PIC Configuratings */
#pragma config FOSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config PWRT = ON
#pragma config DEBUG= OFF

void main(void)
{
TRISCbits.RC0=0;
PORTCbits.RC0=0;

while(1)
{
PORTCbits.RC0=1;
Delay10KTCYx(50);
PORTCbits.RC0=0;
Delay10KTCYx(50);
}
}



Now we’re going to build and program our mcu. First select build. You should receive a confirmation that the project was built successfully.

Once it finishes building, hit the program button.

Congrats! Your LED is flashing at 10hz!

Here how the code works. Out al of the #pragma in the code, pay close attention to #pragma config FOSC =HS. This tells the PIC microcontroller to accept the external cystal we connect. Please note that if we were using the 28pin PIC18 series microcontroller, this would most likely be changed to #pragma config OSC =HS.

Now for the code. Whenever we want to set a particular pin as an output, we have to access the TRISx, where the x stands for the letter of the port we want (in this case, TRISC for PORTC), and write a 0 to that pin. Thus we write TRISCbits.RC0=0 to set PORTC0 as an output. Finally, to either turn on or turn off this particular pin, we just have to write a 0 (off) or 1 (on)  to PORTC. Thus PORTCbits.RC0=0 is setting PORTC0 off.

Finally, the rest of the code is just flashing the LED on and off every 100ms. The while(1) is there to make sure it runs forever.We, that’s all I got for you guys today! Thank you guys for reading! If you have any comments or suggestions, please leave a comment!