Author Archive

Head on over to the Beginner Micro store and check out these cool breadboard modules. These are designed to fit on your breadboard and save you tons of time prototyping your project.  Just imagine having the instant functionality of RS232 to interface your project to your PC or being able to instanly interface to the real world with the relay module.

We just launched our store here at Beginner Micro. Use the Products link in the main menu or just go HERE. We currently are offering several products designed to make life a little easier in the lab and several books on embedded programming by Chuck Hellebuyck.

For those folks looking for a place to get started with developing electronic products, check out our starter kits that have everything you need. started.

If you need a little help getting your PicKit 2TM LED’s to blink, here’s a little program that will get you started.  You’ll see after you run it that I’ve toggled all 4 of the LED’s in two different sequences.  You can play with the different outputs and durations to get familiar with how this is done in C.  I’m using PICC Lite here so don’t forget to “include” the pic.h file into MPLABTM, otherwise it won’t work. 

#include <pic.h>
 __CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & MCLRDIS & PWRTEN & WDTDIS & INTIO);
int i;
int j;
main()
{
PORTC = 0;
TRISC0 = 0;
TRISC1 = 0;
TRISC2 = 0;
TRISC3 = 0;
 j=0;
 while (j<3)
 {
     for (i = 0; i < 5500; i++);
          RC0 = 0;
     for (i = 0; i < 5500; i++);
          RC0 = 1;
     for (i = 0; i < 5500; i++);
          RC1 = 0;
     for (i = 0; i < 5500; i++);
          RC1 = 1;
      for (i = 0; i < 5500; i++);
          RC2 = 0;
     for (i = 0; i < 5500; i++);
          RC2 = 1;
     for (i = 0; i < 5500; i++);
          RC3 = 0;
     for (i = 0; i < 5500; i++);
          RC3 = 1;
     for (i = 0; i < 5500; i++);
          RC2 = 0;
     for (i = 0; i < 5500; i++);
          RC2 = 1;
     for (i = 0; i < 5500; i++);
          RC1 = 0;
     for (i = 0; i < 5500; i++);
          RC1 = 1;
     j=j+1;
 }

j=0;
while (j<5)
{
     for (i = 0; i < 8500; i++);
          PORTC=0b001001;
     for (i = 0; i < 8500; i++);
          PORTC=0b000110;
     for (i = 0; i < 8500; i++);
          PORTC=0b001001;
     for (i = 0; i < 8500; i++);
          PORTC=0b000110;
j=j+1;
}

}

After writing about the PIC hardware PWM module it occurred to me that a little more information about the onboard timers would be in order.  Just about every PIC has a timer and many have several.  The PIC16F777 that we I used in the hardare PWM article has three of them called TMR0, TMR1, TM2

The three timers are similar to each other in many ways but are different in some respects.  Below is a list of each of the timer features from the datasheet.

TRM0

  • 8-bit timer/counter
  • Readable and writable
  • 8-bit software programmable prescaler
  • Internal or external clock select
  • Interrupt on overflow from FFh to 00h
  • Edge select for external clock

TMR1

  • 16-bit timer/counter which consists of two 8-bit registers
  • Readable and writable (TMR1H:TMR1L)
  • 4-bit software programmable prescaler
  • Internal or external clock select

 

TMR2

  • 8-bit timer/counter
  • Readable and writable
  • 4-bit software programmable prescalerInternal or external clock select
  • Prescale options include 1:1, 1:4, 1:16
  • Postcale options include 1:1, 1:2, 1:3, 1:16
  • Internal clock only
  • Output (before prescaler) is fed to the SSP module for an optional shift clock.
  • Can be set to automatically compare it to a value you determine.

Each of the timers can be configured separately and can be used for different purposes within your application.  One of the nice things about these is that they run on their own in the background while your code is off doing something else.  They “tap you on the shoulder” in the form of an interrupt to remind you to go and do something.  You can also read them or reset them at any time.  These timers are essentially binary counters that start at a value you determine and keep running until you shut them off.  If you’re not familiar with a binary counter it looks much like this…

clock pulse 1  00000000
clock pulse 2  00000001
clock pulse 3  00000010
clock pulse 4  00000011
clock pulse 5  00000100
clock pulse 6  00000101

and so on

The counter keeps increasing after every clock pulse until it “overflows”.  Overflows means that when the counter is all 1′s and another 1 is added, there is no place for the carry bit to go.  This generates and interrupt and the timer is reset to all 0′s again.

Now lets write a little routine that uses one of our timers to blink an LED at 1 second intervals.  We’re going to use the CCS compiler for this example and once again use the PIC16F777.  We’ll use TMR1 for this task and take I’ll take a moment to point out a couple of things before we get to coding.

- TMR1 counts from 0 to 65535

- On the next count it resets back to zero and sets a bit in the TMR1IF (Timer 1 Interupt Flag) on the PIR1 register.

- If we run the internal clock at 20Mhz we know that the program counter and the pulses that drive the clock are equal to 1/4 of the internal clock speed of each clock count.  That means that the TMR1 clock runs a 20Mhz/4=5Mhz.

- A little more math and we find that each clock pulse take 1/5Mhz seconds to comple.  That’s .2us for each count of TMR1

- Another piece we need is how long until the timer overflows.  From what we know so far it’s .2us x 65536 = 0.0131

- Since the last piece resulted in such a short time until overflow, we could probably use a prescaler to slow it down a bit. Using the 1:8 prescale which divides our clock we get 5Mz/8 = 625KMz which is 1.6us per count of TMR1.  With that we have 1.6us x 65536 = 0.104856s wich is how long it takes to overflow the clock.

Now, with that information we know that if it takes 0.104856s to overflow the clock.  If we let the clock overflow 10 times we will have taken up 1.04856s.  Well that’s pretty close to what we wanted but lets say we had to get that close to 1s.  What could we do?  Well, remember that TMR one is writable.  That means we can preload a value into TMR to get us a little close.  I’m not going to show all the math on this part but if you solve this equation …

clock cycles = (0.1s)/((20Mhz)(1/4)(1/8)) = 62500

You’ll see that if we could overflow the clock after 62500 cycles rather than 65536 we would have consumed exactly .10 seconds.  So the value we need to preload in is (65335-62500) = 3035.

The code that puts it all together… 

#include <16F777.h>
#fuses INTRC,NOWDT,NOPROTECT
#use delay(clock=2000000)
unsigned int counter = 0;
setup_port_b (ALL_DIGITAL);
#int_timer1

void timer1_isr() {
disable_interrupts(INT_TIMER1); //Turn off interrupts
set_timer1(3035);                                 //Load preset
counter = counter +1;                           //Increment Counter
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);  //Enable the TMR1 Interrupt
}

void main(void){
 SET_TRIS_B( 0×00 );                       //Set Port B to all Outputs
 setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);  //Timer with internal clock and 1:8 prescaler
 enable_interrupts(GLOBAL);
 enable_interrupts(INT_TIMER1);

test: 
if (counter == 10){
 counter = 0;                                              //Reset the counter
 OUTPUT_TOGGLE(PIN_B1);
}

goto test; 

We start out telling the CCS compiler which device we’re using and set some of the config bits.  We also set port B to all outputs, initalize the variable COUNTER, and declare out timer1 interrupt.  The main part of the program sets up the timer with the internal clock and the prescaler we talked about.  The interrupt is enabled and then we begin the testing of the variable COUNTER.  Remember that the TMR1 clock is running all the time now that we’ve set it up.  The test loop checks to see if we’ve overflowed it 10 times.  We know how many times it overflowed because we’ve set up an interrupt routine which increments COUNTER each time if overflows.  When COUNTER reaches ten, we toggle B1.  So with an LED and appropriately sized resister on B1 we would see the LED light up for 1s and then turn off for 1s.

In CCS there are simpler ways of accomplishing this task of lighting the LED for 1s on and 1s off.  We could use the delay function build into CCS to simplify our code.  We only did it this way to demonstrate how the TMR1 operates. Hopefully I’ve shed a little light into the world of PIC timers using CCS and you can feel comfortable using them in your designs.

It’s always helpful to have a list of commonly available capacitors values handy.  If you don’t see what you want here, you may have to put a couple caps in parallel to get what you want.  Here’s a listing of common capacitor values for polarized, non-polarized, and surfacemount caps. 

Non-Polarized Capacitors

10pF 100pF 1000pF .01uF .1uF
12pF 120pF 1200pF .012uF .12uF
15pF 150pF 1500pF .015uF .15uF
18pF 180pF .0018uF .018uF .18uF
22pF 220pF .0022uF .022uF .22uF
27pF 270pF .0027uF .027uF .27uF
33pF 330pF .0033uF .033uF .33uF
39pF 390pF .0039uF .039uF .39uF
47uF 470pF .0047uF .047uF .47uf
56pF 560pF      
68pF 680pF      
82pF 820pF

Polarized Capacitors

1.0uF 10uF 100uF 1000uF
1.5uF 15uF 150uF 1500uF
2.2uF 22uF 220uF  
3.3uF 33uF 330uF  
4.7uF 47uF 470uF  
6.8uF 68uF 680uF  

As I was trying to think of a topic to write on this week, I noticed my ten year old son was playing on my bench trying to light up an LED with a battery.  I was mildly entertained as he would smile when the light came on and then frown when it would turn off.  “What happened?” he would say.  I let him continue for a little while until I realized he was quickly working his way through my inventory of red LED’s.  What my son didn’t realize is that he was either connecting them backwards and/or not properly limiting the current to the LED in which case he was burning them out.  So yes, an idea on what to write about was born.

As with most things that we set out to do, we need to understand the components that we’re working with.  We don’t need to become an expert on LED’s to use one but some basic understanding is helpful.  A good place to start with understanding an electrical component is the datasheet.  A popular LED is the red 4mm leaded package so we’ll work with that one.

Before we get started, it’s important to point out that an LED is a Light Emitting Diode.  This means that it is essentially a diode that lights up.  And with diodes we know that current can only flow in one direction, that is, the direction the diode is pointing.  If you turn it around, no current will flow, and it will not light up.  When it’s used in its proper orientation, it will pass current, have a voltage drop, and give off light.

The first thing you’ll see in the datasheet is the package drawing.  This is, of course, helpful in giving you a feel for the size of the key features of the component but I’d also like you to notice the leads.  LED’s have two leads called the Anode and the Cathode.  The Anode is the positive terminal and the Cathode is the negative terminal.  The longer lead is the Anode.  This will help you to properly insert your LED into your breadboard or PCB with the correct polarity.

 

 

led-drawing-color

Another feature of the package is that when you look at the LED from the top, you’ll notice there’s a flat side which corresponds with the shorter lead or Cathode.  The schematic for an LED is shown below.  Sometimes an LED schematic symbol will be circled but I’m showing the default symbol used in PCB Express Schematic.

led-symbol

I’m not going to go into such topics as Luminous Intensity and Wavelengths in this tutorial but may discuss it in a future article.   It’s not that these topics aren’t important, it’s just that my goal here is to get you up and running.  With that said, lets move on to sizing your current limiting resistor.

What’s a current limiting resistor?  Well, it’s the resistor in the small circuit shown below.

diode-circuit

Its purpose is to “limit” the current in the circuit so that the LED is fed the proper level for operation.  So how does it do that?  Let’s take a look at this equation referred to as Ohm’s Law.

V = IxR

V = Voltage expressed in Volts
I = Current expressed in Amps
R = Resistance expressed in  Ohms

A slight modification to this equation results in the expression …

R = V / I

So if you know the voltage and the desired current, you can calculate the resistance needed to make that happen.

So how do I know what V and I are?  Well, let’s go back to the datasheet.  You should see a chart similar to the one below.

diode-chart

This chart shows the LED’s characteristic relationship between Forward Voltage and Forward Current.  These two values are exactly what we’re looking for.  This not only shows the operating range of current and voltage but shows how one affects the other.

One good practice when picking values is to pick values near the middle of the range.  This will give you a nice safety margin on both sides.   Let’s go back to our LED circuit for a moment.  This time, I’ve declared what my battery voltage is.  You need to know what this is going to be to select an appropriate resistor.  For our circuit, we have selected 5 Volts for the battery.

diode-circuit

Now keep in mind that your circuit may not look exactly like this one.  Yours may look like the one below.

diode-pic-circuit

If your output pins on your PIC are running at 5 volts then your circuit is essentially the same as the one with the battery.  If we’re talking about a PIC though, I know one more piece of information which is important.  I know that the max current we should have is 20mA.  This is the datasheet max for PIC devices.  If we go beyond this value for too long, our PIC can get a little toasty.

So after we know our voltage we know all the following…

-    Our source voltage is 5 Volts
-    Our max current is 20 mA
-    The resistor will have a current drop
-    Our LED will have a voltage drop
-    I know that the sum of the drop of the Voltage across the Resistor and the LED will equal 5 Volts.

Let’s go back to our LED Datasheet chart above.  If I pick a value in the middle of the range, say 2 Volts, what is our current (I)?  I’m seeing about 8mA which is well within our max of 20mA.

So, with a voltage drop across the LED of 2 volts that gives us a voltage drop across the resistor of 3V (5 V – 2 V = 3V).  Now we can use our equation for Ohms Law to calculate the value of the resistor that will give is a 3 V drop.

R = V /  I
R = 3 V/  8 mA
R =  375 Ohms

So what we’re looking for is a 375 Ohm resistor, which I can tell you without even looking that it doesn’t exist.  What we need to do is find the closest value that does exist and recalculate our values to make sure we don’t exceed our requirements.

The closest standard resistor value to 375 Ohms is 360 Ohms for a ¼ Watt 5% tolerance resistor.  Let’s recalculate using that value and make sure our current is within our operating range.

I = V / R
I = 3 / 360
I  = 8.33ma (Good)

Even though I’m pretty sure we’re OK, let’s go ahead and calculate the power that will be consumed by the Resistor in the circuit.  The equation for that is…

P = VxI
P = 3V x 8.33mA
P = 0.025 W (Good since limit is 0.25)

Now keep in mind that that if you consistently use the same power source and similar PIC’s, you don’t need to recalculate this every time.  Just use the same type of LED for most of your projects and buy a bag of resistors of the appropriate value.

I tried to explain all this stuff to my son after he systematically worked through a chunk of my red LED’s.  He nodded and smiled as I worked through the math but clearly he just wanted me to tell him what resistor to use.  I handed him a bag of 360 Ohm resistors and went on my way.

Pulse Width Modulation (PWM) signals in the embedded world are used all the time for a variety of reasons.  One use is to communicate.  For example, on most Ford cars and trucks the regulator communicates status of the alternator field coil back to the engine control module.  If the duty cycle of the the PWM is between 10-90% it means that the alternator is working just fine and if it gets into the 0-10% or 90-100% there’s a problem.  You could also control the power output of your headlights with PWM.  This is how most daytime running lights are done.  Some still switch into a resistor to knock down the power, but in todays world that’s just not efficient enough.  We can also control the “theatre lighting” of our vehicle’s interior lights.  Using PWM we can gradually brighten or darken the cars interior or we can take tricolor LEDs and change the color of our interior.

So how do we get started using PWM’s on our PICs?  Well, like most things we want to do we need to look at the datasheet of the device we want to work with.  If you have hardware PWM as one of the features on your device, you’re already ahead of the game.  If you don’t, you may find yourself doing a little programming to create a PWM.  Not a huge deal but keep in mind the code will have to periodically service your PWM which takes it away from doing other things you might rather be doing.  Hardware PWM is more of a set it and forget it (until you want to change the duty cycle or turn it off) kind of thing.  I’m all for simplicity so I recommend selecting a device with a hardware PWM.

I’m currently working with the PIC16F777.  It’s a 40 pin PDIP  that has 2 hardware PWM’s on board.  These are part of the Capture/Compare/PWM module.  Each one of these contains a 16 bit register which can operate as a :

* 16-bit Capture register
* 16-bit Compare register
* PWM Master/Slave Duty Cycle register

I’m going to try not to duplicate the datasheet because you can read that along with this article.  What I’d like to do is communicate what the datasheet means in regards to making this happen in the CCS compiler.

 

pwm

Take a look at the above signal that is shown in the datasheet.  This shows us much of what we need to know.  The PWM signal uses TMR2 (Timer2) to clock the Period of the signal as well as the duty cycle.  Now one thing that is a little confusing about the graph is the Duty Cycle.  I believe it should be labled more like “Time High” rather than Duty Cycle.  I think of the Duty Cycle as a percentage of time high vs. the period of the signal.  So for example if the perod measured in seconds is 100ms (or .1s) and the time high 10ms (or .01s) the duty cycle is 10%.

Let’s jump into CCS mode here and talk about what we need to do.  First of all, we need to let the PIC know that we intend to use the CCP modules as PWM.  In CCS that looks like this…

setup_ccp1(CCP_PWM);   //Config CCP1 as a PWM

Pretty simple right?  The next thing we need to do is set up the timer2.  This requires a little bit of math.  In our example we want to generate a PWM that has a 100Hz frequency.  Using the formula:  Period (T) = 1/frequency, the Period will be .01 seconds long.  I’d also like the time high to be adjustable from 0s to .01s which is essentially 0% to 100% duty cycle.  The math is going to get a little heavy for a moment but hang in there.  I’ve attached a spreadsheet which does much of this stuff for you.

OK, to set up the timer2 we need to know what speed we want the micro to run.  The PIC16F777 can be set for a variety of clock speeds.  We’re going to pick 1Mhz for this little project.  I could go up to 8Mhz but we just don’t need that kind of speed for what we’re doing.  So before we go into our Main routine we’re going to direct the the compiler to set then device to a PIC16F777, use the internal clock, turn off the watchdog timer, and leave our code unprotected.  More about the watchdog and code protection as the focus in another article.  Here’s the code that does this…

#include <16F777.h>
#fuses INTRC,NOWDT,NOPROTECT
#use delay(clock=1000000)

These lines will be at the very beginning of your program.  Don’t worry, because we’re going to put them all together at the end.

So back to the timer stuff.  The CCS compiler guide tells us that for in order to setup the timer2 we need to understand a little bit more about it.  The timer2 is 8-bit on pic16s and pic18s.  It counts up and will provide an interupt when it overflows.  This interupt is important to us even though we won’t have to service it.  When we use CCS’s setup_timer_2 function, the compiler will take care of it for us.  This function is in the form of..

setup_timer_2(mode, period,postscale)

where we provide the mode, period, and postscale we need to get what we want out of the PWM.  For our requirement it looks like this…

setup_timer_2(T2_DIV_BY_16, 156, 1)

T2_DIV_BY_16 is the prescale of the clock.  We could use another value here like T2_DIV_BY_8 but it would change our period and we would have to calculate another value for it because our PWM frequency would now be twice what we were designing for.  156 is the period (or cycle time) in clock cycles.  Timer2 will start, make the output high, and after 156 clock cycles it will generate an interupt and raise the pin again from whatever state it’s in.  This is all that we need for the timer2 because the postscale can stay at 1.

Now, on to the final CCS command which sets the time we want the PWM to be high within the period.  It takes the form…

set_pwm1_duty=(value)

where value is the number of clock cycles we want the clock to keep the pin high.  This one is pretty straight forward.

Now, putting it all together.

//*********************************************

#include <16F777.h>
#fuses INTRC,NOWDT,NOPROTECT
#use delay(clock=1000000)

void main(void)
{
unsigned int pwm1
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16, 156, 1);
while( TRUE ) {
pwm1=80; //duty cycle
set_pwm1_duty(pwm1);
}
}

You should be able to recognize all the pieces of the above snippet and have a fully running PWM on CCP1 which is pin 17.  You change the pwm1 variable to any number between 0 and 156 to change the duty cycle of your pwm signal.  At the current value of 80 it’s pretty close to 50% duty.

OK, here’s the spreadsheet to help calculate these values.  Keep in mind it’s not the greatest in that you have to play around with the values a bit in order to get the output you want.  I didn’t set it up so you can just enter the Cycle Time and frequency and it gives you the other parameters.  It works the other way where you start with a decent guess as far as the clock and prescaler goes and tweak until you get the output you want.  It definately can use some improvement but it works.

mplab-sim-screenshot