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);
}


Projects: Pygames Controller Final Update

Well, I head back to RPI next Sunday. I finally can say I finally finished building the prototype of my Pygames Controller and successfully completed the “before I go back to RPI” requirement. The only thing I wished I could of adding for the project is a decoupling capacitor for each button. Otherwise, I am very proud of the prototype. The code for the project can be found at the following URL.  Feel free to post any problems or concerns you have about the code, and I will make sure I add it to the next version of the controller.Now I change the project status to complete on the projects page 😀 In fact, for now on, instead of placing code in these blog posts, I will upload code to Github. Anyway, I see you guys later!

Mini Projects: XBees Wireless Module and 74HC4052

First off, I would like to say Happy New Year everyone! Apparently we all survived after all. Anyway, for the past couple of weeks, I started to mess around with X-Bees wireless modules. First off, what are X-Bees? X-Bees are a special type of chip that allows you communicate microcontrollers and computers together using serial communication.

There was a great deal of frustration when using these chips. First off, I soldered the X-Bees to the wrong side of the breakout board. It took me quite some time for me to realize the soldering mistake. Then I tried running the modules at an 115200 baudrate, which proved to be too much for the wireless module. Finally I got the modules communicating with each other when I programmed the PIC18F4553 to send “Hello World” to the computer. Although I managed to transmit the message wirelessly, the propagation distance was terrible. In fact, I could only get a transmission distance of a 1 foot. I began to wonder why the propagation distance was so low. Then I realized that the X-Bees I brought did not include the necessary antenna needed. After realizing this fluke, I quickly went to Sparkfun and brought the necessary antennas, which will not come in until next week.

The final object I brought was a 74HC4052. What’s so amazing about this chip? It’s actually a multiplexer/de-multiplexer chip designed especially for analog and serial devices. In other words, you can connect up to 8 serial/analog devices using one microcontroller. I did an initial test which I connected my serial LCD to one pin, and the serial port of the computer to the other serial port. It took me some time make the right connections and debugged the hardware, but it worked marvelously afterwards. Overall, I think this chip is amazing! Previously, I was trying to think of a way to connect three of my serial devices using one microcontroller. However, after using chip, this will become a default option for me. In fact, you guys can expect a tutorial on how to use the chip this Friday.

Projects: Pygames Controller Update #1

So last Monday, my parts for all of my Pygames controller project, which was previously my N64 emulator controller project,came in. The parts included two analog sticks taken from a PS2 controller, 12 large tactile buttons, 2 triggers taken from an X-Box 360 controller, and breakout boards for the analog sticks and the X-Box 360 triggers.However, I had two very unpleasant surprises when I opened my package. The first problem was the absence of solder for the breakout boards. I had to wait until Wednesday to get the right solder for the breakout board. The last nasty surprise was one of the X-Box 360 controller triggers were broken. Since one of the triggers was broken, I’ll just make due without them. The triggers will be added to a future version of the controller.

On Wednesday, I finally got some cheap solder from Radioshack. After going to Radioshack, I immediately soldered the analog sticks to their respective breakout board. Once I finished soldering, I quickly started to write test code for one of the analog sticks. Normally, I would use an USART terminal window like the serial window from the Arduino IDE to see the values from the analog stick, but I wanted to do something different. Instead, I used my 160×120 serial LCD as a debug window. As you see in the figure above, the debug window shows digital values associated with the horizontal and vertical pots of the joystick.

Afterwards, I started to write the actual code of the PIC MCU side of the controller. As of right now, the controller will have four listed functions:
IsControllerConnected (): Checks to see if the controller is connected to the computer. Returns 1 for true and 0 for false.
ReadJoystickX(): Read the state of the joystick’s x direction for the controller. Returns 0 for the neutral position, 1 for right and -1 for left.
ReadJoystickY (): Read the state of the joystick’s y direction for the controller. Returns 0 for neutral position, 1 for up and -1 for down.
IsButtonPressed () : Checks to see if the button is pressed. Returns 1 for true, and 0 for false.

I spent all of Thursday to write for the PIC MCU side of the controller. To make coding a little bit more organized, I decided to create 3 structures: joystick, button, and controller. Here’s the initial controller.h file.

#include &lt;p18f4553.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;usart.h&gt;
#include &lt;delays.h&gt;
#include &lt;delays.h&gt;
#include &lt;portb.h&gt;
//===============================================================================================
//	Joystick Structure
//===============================================================================================
typedef struct
{
int X_ADC_CHANNEL;			//	ADC channel for the horizontal component of the joystick
int Y_ADC_CHANNEL;			//	ADC channel for the vertical component of the joystick
}JOYSTICK;
//===============================================================================================
//
//===============================================================================================

//===============================================================================================
//	Button Structure
//===============================================================================================
typedef struct
{
unsigned int BUTTON_PIN;		//	Pin which the button is connected to
}BUTTON;
//===============================================================================================
//
//===============================================================================================

//===============================================================================================
//	Controller Structure
//===============================================================================================
typedef struct
{
JOYSTICK LEFT_JOYSTICK;				//	Left Joystick
JOYSTICK RIGHT_JOYSTICK;			//	Right Joystick
BUTTON	YELLOW_BUTTON;				//	Yellow Button
BUTTON	RED_BUTTON;                             //	Red Button
BUTTON	GREEN_BUTTON;				//	Green Button
BUTTON	BLUE_BUTTON;				//	Blue Button
}CONTROLLER;
//===============================================================================================
//
//===============================================================================================

void CONTROLLER_INIT(CONTROLLER MY_CONTROLLER);
unsigned int ISBUTTONPRESSED(BUTTON MY_BUTTON);


I finished 3/4 of the code, until I ran into a stumbling block with creating the header files and the c files for the controller. Since my controller.h and controller.c needed to use the provided pic18f4553.h library to work, I had some difficulty figuring out how to include the file for not only my controller.c but also my main.c.However, I solved the problem by using ifndef, define, and endif.

#ifndef CONTROLLER_H
#define CONTROLLER_H
#include &lt;p18f4553.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;usart.h&gt;
#include &lt;delays.h&gt;
#include &lt;delays.h&gt;
#include &lt;portb.h&gt;
//===============================================================================================
//	Joystick Structure
//===============================================================================================
typedef struct
{
int X_ADC_CHANNEL;			//	ADC channel for the horizontal component of the joystick
int Y_ADC_CHANNEL;			//	ADC channel for the vertical component of the joystick
}JOYSTICK;
//===============================================================================================
//
//===============================================================================================

//===============================================================================================
//	Button Structure
//===============================================================================================
typedef struct
{
unsigned int BUTTON_PIN;		//	Pin which the button is connected to
}BUTTON;
//===============================================================================================
//
//===============================================================================================

//===============================================================================================
//	Controller Structure
//===============================================================================================
typedef struct
{
JOYSTICK LEFT_JOYSTICK;				//	Left Joystick
JOYSTICK RIGHT_JOYSTICK;			//	Right Joystick
BUTTON	YELLOW_BUTTON;				//	Yellow Button
BUTTON	RED_BUTTON;                             //	Red Button
BUTTON	GREEN_BUTTON;				//	Green Button
BUTTON	BLUE_BUTTON;				//	Blue Button
}CONTROLLER;
//===============================================================================================
//
//===============================================================================================

void CONTROLLER_INIT(CONTROLLER MY_CONTROLLER);
unsigned int ISBUTTONPRESSED(BUTTON MY_BUTTON);
#endif


From reading a couple tutorials on creating .h files, this piece of code made sure the header files included in the other .h file gets read. Although the problem with creating the .h and .c files was solved, a new problem occurred. Apparently, the function I wrote to set the ADC channel for the horizontal and vertical components of the joystick was not set, which caused a huge mess in my ADC readings. I simply solved this problem by passing my structures by reference whenever I need to use them for a function. I forgot that to edit the values from a structure, they must be passed by reference. Here’s the current version of my controller.h file.

#ifndef CONTROLLER_H
#define CONTROLLER_H
#include &lt;p18f4553.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;usart.h&gt;
#include &lt;delays.h&gt;
#include &lt;delays.h&gt;
#include &lt;portb.h&gt;
//===============================================================================================
//	Joystick Structure
//===============================================================================================
typedef struct
{
int X_ADC_CHANNEL;			//	ADC channel for the horizontal component of the joystick
int Y_ADC_CHANNEL;			//	ADC channel for the vertical component of the joystick
}JOYSTICK;
//===============================================================================================
//
//===============================================================================================

//===============================================================================================
//	Button Structure
//===============================================================================================
typedef struct
{
unsigned int BUTTON_PIN;		//	Pin which the button is connected to
}BUTTON;
//===============================================================================================
//
//===============================================================================================

//===============================================================================================
//	Controller Structure
//===============================================================================================
typedef struct
{
JOYSTICK LEFT_JOYSTICK;				//	Left Joystick
JOYSTICK RIGHT_JOYSTICK;			//	Right Joystick
BUTTON	YELLOW_BUTTON;				//	Yellow Button
BUTTON	RED_BUTTON;                             //	Red Button
BUTTON	GREEN_BUTTON;				//	Green Button
BUTTON	BLUE_BUTTON;				//	Blue Button
}CONTROLLER;
//===============================================================================================
//
//===============================================================================================

void CONTROLLER_INIT(CONTROLLER * MY_CONTROLLER);
unsigned int ISBUTTONPRESSED(BUTTON * MY_BUTTON);
#endif


I’m still trying to finish up my controller.c code, but I got it working to a point where the code can tell if the joystick is pointing left, pointing right, or in the neutral position.

Hopefully I should finish the PIC MCU side of the Pygames controller sometime this weekend if not next week. Anyway, hope you guys have a good weekend!

Mini Projects: 160×128 Serial LCD and RFID Fun

So lately I’ve been messing around with alot of electronic components lately. One of these beauties is a 160×120 LCD screen. I will admit, they seemed a little daunting at first, but I was fairly surprised how easy it is using these LCD screens.  From what I’ve seen thus far, special commands are executed by sending the hex value 0x7C followed by the proper command. For example, to reset the display, I just need to send 0x7C then 0x00. Of course, to add text to the display, just send an ASCII message to the display. I did not do anything with boxes or lines yet, but will be part of my agenda.

The last new item I used this week was a RFID ID-120 reader. Like the 160×120 display, it’s controlled via serial. Apparently, this item beauty was shown in Blidr, and the pseudo code for reading the RFID tag was very simple.  In fact, I re-wrote the code to be used with the PIC18F4553, which I will post a tutorial on how to use it before I go back to RPI.

The picture above shows the tag of one of the RFID’s after I ran my RFID reader code on the PIC18F4553. It’s a little slow reading the tag at times, but I find it very reliable.  Well, that’s it for me this week! See you guys on Monday….o wait. The world is gonna end today. Well, it’s nice knowing you guys!

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!

Projects: N64 Emulator Controller Update #2

Yesterday, I just placed the order from Sparkfun for the prototype of the controller. The prototype will be implemented on a breadboard first before progressing any further. As you guys can tell from the shopping cart, I brought 12 tact switches with a nice round top on each one, left and right bumpers, and two analog sticks. One analog stick will be for the analog stick on the N64 and the other analog stick will be for the C buttons. The reason why I’m mapping the C buttons to an analog stick is because I figured I could create a controller similar to a PS3 or 360 controller, which feels natural to me. I have no idea how long it will take the order to get here in Philadelphia, but my guess is next week before Christmas.

Anyway, I started to mess around with the serial library for Python. Using the library was much more simpler than I thought as there are plenty of documentation on how to use the library. To understand how the library works, I wrote a simple little code in python that not only sends the letter c to the PIC microcontroller, but waits up to 1 seconds for the PIC microcontroller to send “hello” to it. Originally, I wanted to paste the code to this paste, however, the code editor for wordpress is really poor and will mess up the coding syntax of Python. The way the code works is that whenever I’m prompted to enter a character, it will either exit the program, or transmit the letter ‘c’ to the PIC18F4553 microcontroller. When the microcontroller pick up the c, it will transmit “hello” to the computer.

It seems like there are some timing issues since I get a weird character after the first transmission. I’m going to look into how to resolve this issue until the parts come in. I will also learn how the keyboard event generator will work in Python.