Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC12F675 Software PWM - LED Driver

Status
Not open for further replies.

wuchy143

Member
Hi All,

I see that there are not many PWM examples in regards to software PWM on Microchips PIC12F675. Or at least useful examples were not easily found when I googled it and since I took the time to write my own maybe someone could use it.

Please be warned. In my design the PIC12F675's ONLY job is to do PWM and that's it. If you need to do other useful things like be a UART...or anything that takes time...then this code will probably be useless to you.

Operation:

I attached the schematic. Essentially I read two port pins(GP5 and 3) to determine the LED brightness. So GP3 goes low the LED intensity goes up. GP5 goes low the LED intensity goes low.

After ~5 seconds of the user not changing the brightness the PIC saves the value in E^2 so it can remember the brightness level if power is lost.

I did put a small bit of hysteresis on the switches.

Any questions/comments good or bad please let me know.

Enjoy.

-mike

Code:
 void PWM(void);
 void Read_Buttons(void);

  const unsigned int PWM_Inputs[200] =
  { 200, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 197, 197, 197,
    197, 197, 196, 196, 196, 196, 196, 195, 195, 195, 195, 195, 194, 194,
    194, 194, 194, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 191,
    191, 191, 191, 191, 190, 190, 190, 190, 190, 189, 189, 189, 189, 189,
    188, 188, 188, 188, 188, 187, 187, 187, 187, 187, 186, 186, 186, 186,
    186, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 183, 183, 183,
    183, 183, 182, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180,
    180, 175, 175, 175, 170, 170, 170, 165, 165, 165, 160, 160, 160, 160,
    155, 155, 155, 150, 150, 150, 145, 145, 145, 140, 140, 140, 135, 135,
    135, 130, 130, 130, 125, 125, 125, 120, 120, 120, 115, 115, 115, 100,
    100, 100,  95,  95,  95,  90,  90,  90,  80,  80,  80,  70,  70,  70,
     70,  70,  60,  60,  60,  60,  60,  50,  50,  50,  50,  50,  40,  40,
     40,  40,  40,  30,  30,  30,  30,  30,  20,  20,  20,  20,  20,  15,
     15,  15,  15,  15,  10,  10,  10,  10,  10,   5,   5,   5,   5,   1,
     1,   1,   1,   1};
  
 //---------------------------------------------------------------------------//
 //--------------------------   VARIABLE INITIALIZATION   --------------------//
 //---------------------------------------------------------------------------//
 unsigned int Time = 0x00;
 unsigned int Duty_Cycle = 0x00;
 unsigned int Duty_Cycle_Mirror = 0x00;
 unsigned int i = 0x00;
 unsigned int debounce = 0x00;


void main()
{
CMCON    = 0x00;                // Disable comparators
ANSEL    = 0b00000000;          //assigning digital i/o all ports
TRISIO   = 0b00101000;          //setting ports GP3(pin4) / GP5(pin2) to inputs

//fetch previous backlight intensity before powerdown
Duty_Cycle = EEPROM_Read(0);

if(Duty_Cycle > 200)
{
    Duty_Cycle = 0;
    Duty_Cycle_Mirror = 0;
}
else
{
Duty_Cycle_Mirror = Duty_Cycle;
}

//----------------------------------------------------------------------------//
//-----------------------------   MAIN LOOP   --------------------------------//
//----------------------------------------------------------------------------//
while(1)
       {
       PWM();
       Read_Buttons();
       i++;
       if(i >= 385 && (Duty_Cycle != Duty_Cycle_Mirror))
            {
               Duty_Cycle_Mirror = Duty_Cycle;
               i = 0;
               GP4_bit ^= 1;
               EEPROM_Write(0, Duty_Cycle_Mirror);
            }
       Read_Buttons();
}
}

void PWM(void)
{        Time = 0;
         while(Time <= 200)
            {
               if(Time > PWM_Inputs[Duty_Cycle])
               {
               Time++;
               GP2_bit = 0;
               }
               else
               {
               GP2_bit = 1;
               Time++;
               }
            }
}

void Read_Buttons(void)
{
   if(GP3_bit == 0)
   {
        i = 0;
        debounce++;
        if((Duty_Cycle < 199) && (debounce >= 2))
        {
        debounce = 0;
        Duty_Cycle++;
        }
   }
   if(GP5_bit == 0)
   {
        i = 0;
        debounce++;
        if((Duty_Cycle > 0) && (debounce >= 2))
        {
        debounce = 0;
        Duty_Cycle--;
        }
   }
}
 
Questions:

1) What's D130 for, faster off-fall vs slower-on rise time?
2) 1K limits LED current to 3mA with a 2 Vf LED drop, that's a bit low for full brightness.
3) A Pfet is usually more expensive & less efficient @ switching than an NFET given Rds On and rise time.
4) Why not use the Weak pull ups rather than external 10K resistors.
5) 0 Ohm resistors in a schematic? One pulling an i/o to ground with a 10K going to Vdd and the other shorting the switching FET Drain to Source.


edit:I fear K8LH is confusing me with someone else.
 
Last edited:
Mike (wuchy143),

Thank you for posting. Would you mind mentioning which C compiler you're using for those members who might like to duplicate your example?

Cheerful regards, Mike
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top