[PIC] Code for LED brightness control using PWM in PIC18F47J53

Status
Not open for further replies.

anim1

Newbie level 4
Joined
Aug 10, 2017
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
40
Hi everyone,

I am using a PIC Clicker which contains PIC18F47J53 on-board. It will be very helpful if someone can provide me a sample C code to control LED brightness using PWM. I have went through the datasheet but I am unable to figure out the syntax as I am a newbie.

Thanks in advance.

Anim.
 
Last edited:

Provide more details like,

What Compiler are you using ?
What is the Crystal frequency on PIC Clicker ?
What pin the Led is connected to that is which PWM channel it uses ?
To which pin POT is connected to control the brightness of the Led based on ADC value ?
 

i am too big of a newbie , but i found a way to make a project. This is an easy project that can be set up in minutes with no experience. All you need is an Arduino (I used an Uno), a breadboard and jumper caples, two push buttons and an LED - check equipment LEDs. Two push buttons with pull-down resistors are used to control an LED on pin 13. The pushbutton on pin 10 raises the LED's brightness. The pushbutton on pin 9 lowers the LED's brightness.


Code:
const int brightnessUp = 10;     // the number of the pushbutton pin
const int brightnessDown = 9;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
const int maxBrightness = 12; //this can be any number - it's the number of steps between dimmest and brightest. 

// variables will change:
int brightness = maxBrightness;
int interval=1;

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pins as an input:
  pinMode(brightnessUp, INPUT);     
  pinMode(brightnessDown, INPUT);   
  Serial.begin(9600);
}

void loop(){
    if (digitalRead(brightnessUp) == HIGH && brightness < maxBrightness){ 
      brightness = brightness + interval; 
      //if the brightness Up button is pushed, add one degree of brightness to the current level
      Serial.println(brightness); //for debugging purposes
    }
    if (digitalRead(brightnessDown) == HIGH && brightness > 0){
      brightness = brightness - interval;
      //if the brightness Down button is pushed, subtract one degree of brightness from the current level
      Serial.println(brightness); //for debugging purposes
    }
    delay(100);
    analogWrite(ledPin, map(brightness, 0, maxBrightness, 0, 255));
//this code maps the max brightness constant to the max LED brightness
 


Hi,

/I am using MikroC.
/Crystal Frequency is 16 Mhz.
/LED is connected on RA0 nd RA1, PWM is connected on RC6.
/I actually want the LED brightness to be controled automatically as sine wave.

Thanks,
Anim
 

How is the Led connected to RA0 ? Led cathode to RA0 or abode to RA0 ?
 

How is the Led connected to RA0 ? Led cathode to RA0 or abode to RA0 ?

PIC clicker is actually a starter development kit, everything is integrated.
 

Yes, I have that PIC Clicker development board. I made a code but it is not working. Some problem related to PPS Mapping or ECCP2 PWM. I have to contact mikroE support. I will have a chat with mikroE support tomorrow. They will be able to provide solution to the problem.

Here is the code. According to my code duty first changes from 0 to max (255) and then from max to 0.

5 sec is taken as the time to reach limits.

5000 ms / 255 = ~20ms

20ms delay is used in the loops.

Code:
signed int pwm_duty = 0;

void main() {

    CM1CON = 0x00;
    CM2CON = 0x00;
    
    CVRCON = 0x00;
    
    ADCON0 = 0x00;
    ADCON1 = 0x80;
    ANCON0 = 0xFF;
    ANCON1 = 0xFF;
    
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;

    Delay_ms(100);

    Unlock_IOLOCK();
    PPS_Mapping_NoLock(19, _OUTPUT, _P1B);
    Lock_IOLOCK();
    
    PWM2_Remappable_Init(2000);
    PWM2_Remappable_Set_Duty(0);
    PWM2_Remappable_Start();

    while(1) {

           for(pwm_duty = 0; pwm_duty < 256; pwm_duty++) {
               PWM2_Remappable_Set_Duty((unsigned short)pwm_duty);
               Delay_ms(20);
           }
           
           for(pwm_duty = 255; pwm_duty >= 0; pwm_duty--) {
               PWM2_Remappable_Set_Duty((unsigned short)pwm_duty);
               Delay_ms(20);
           }
    }
}
 

Attachments

  • Led Brightness Control Using PWM.rar
    46.4 KB · Views: 117

A simple PWM on RC6 pin should be able to change the brightness of the LED.
 


Thanks, Will be glad if you can let me know If you find a solution.
 

@kasipunye1

On PIC Clicker board Leds are connected to RA0 and RA1.



Hi

I already fixed the code and it was working. I was busy with some other work.

Here is the code. It is now working. I tested it on PIC Clicker and also Proteus. Also find attached project files.

PPS Mapping code had issues. Issue was I had to replace

Code:
PPS_Mapping_NoLock(15, _OUTPUT, _CCP1_P1A);

with


Code:
PPS_Mapping_NoLock(0, _OUTPUT, _CCP1_P1A);

For rp_pin argument I was considering pin number instead of remappable pin number.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
signed int pwm_duty = 0;
 
void main() {
 
    CM1CON = 0x00;
    CM2CON = 0x00;
    
    CVRCON = 0x00;
    
    ADCON0 = 0x00;
    ADCON1 = 0x80;
    ANCON0 = 0xFF;
    ANCON1 = 0xFF;
    
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
 
    Delay_ms(100);
 
    Unlock_IOLOCK();
    PPS_Mapping_NoLock(0, _OUTPUT, _CCP1_P1A);
    Lock_IOLOCK();
    
    PWM1_Remappable_Init(2000);
    PWM1_Remappable_Set_Duty(0);
    PWM1_Remappable_Start();
 
    while(1) {
 
           for(pwm_duty = 0; pwm_duty < 256; pwm_duty++) {
               PWM1_Remappable_Set_Duty((unsigned short)pwm_duty);
               Delay_ms(20);
           }
           
           for(pwm_duty = 255; pwm_duty >= 0; pwm_duty--) {
               PWM1_Remappable_Set_Duty((unsigned short)pwm_duty);
               Delay_ms(20);
           }
    }
}

 

Attachments

  • Led Brightness Control Using PWM - Fixed Working.rar
    39.7 KB · Views: 109

hello,

i didn't check your program, BUT :
if pmt_duty <0 => gives 65535 !

so correct this
Code:
for(pwm_duty = 255; pwm_duty > 0; pwm_duty--)

prnt out of pwm_duty:



:???: Mistake !
with >0 ,never go to zero ..
Problem can occurs only with unsigned int ...
it is OK with signed int ..
 
Last edited:

I have used

Code:
signed int pwm_duty = 0;

@paulfjujo

You are right. It was a bug. Your code is correct. I fixed it.

Code:
for(pwm_duty = 255; pwm_duty > 0; pwm_duty--) {
               PWM1_Remappable_Set_Duty((unsigned short)pwm_duty);
               Delay_ms(20);
           }
 

hello Baileychic,


I said i did a mistake because with this code :
for(pwm_duty = 255; pwm_duty > 0; pwm_duty--)
you never get the zero value .. minima is 1
and with pwm_duty >=0 you count down until the zero value..

i don't know if you want to pass to by zero value or not in you application.

The problem exist only if pwm_duty is declared as an unsigned int .. with test >=0 => overflow 0 to 65535
 

Hi @baileychic ,

Thanks a lot. Just last question. If I want to control both LED what should I do? I have tried by changing your code to-
TRISA.RA0 = 0x00;
TRISA.RA1 = 0x00;

But that didn't worked, I guess it is not the right way. If you know how to do with both LED at the same time please let me know.

Thanks,
anim
 

Here is the PWm on two leds code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#define Pwm_method_1
 
signed int pwm_duty[2] = {0, 0};
 
void Set_Pwm_Duty() {
    PWM1_Remappable_Set_Duty((unsigned short)pwm_duty[0]);
    
    #ifdef Pwm_Method_1
        PWM2_Remappable_Set_Duty((unsigned short)pwm_duty[1]);
    #else
        PWM2_Remappable_Set_Duty(255 - (unsigned short)pwm_duty[0]);
    #endif
 
    Delay_ms(20);
}
 
void main() {
 
    CM1CON = 0x00;
    CM2CON = 0x00;
    
    CVRCON = 0x00;
    
    ADCON0 = 0x00;
    ADCON1 = 0x80;
    ANCON0 = 0xFF;
    ANCON1 = 0xFF;
    
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
 
    Delay_ms(100);
 
    Unlock_IOLOCK();
    PPS_Mapping_NoLock(0, _OUTPUT, _CCP1_P1A);
    PPS_Mapping_NoLock(1, _OUTPUT, _CCP2_P2A);
    Lock_IOLOCK();
    
    PWM1_Remappable_Init(2000);
    PWM1_Remappable_Set_Duty(0);
    PWM1_Remappable_Start();
    
    PWM2_Remappable_Init(2000);
    PWM2_Remappable_Set_Duty(255);
    PWM2_Remappable_Start();
 
    while(1) {
 
           #ifdef Pwm_Method_1
               for(pwm_duty[0] = 0, pwm_duty[1] = 255; pwm_duty[0] < 256, pwm_duty[1] > 0; pwm_duty[0]++, pwm_duty[1]--) {
                    Set_Pwm_Duty();
               }
 
               for(pwm_duty[0] = 255, pwm_duty[1] = 0; pwm_duty[0] > 0, pwm_duty[1] < 256; pwm_duty[0]--, pwm_duty[1]++) {
                   Set_Pwm_Duty();
               }
           #else
               for(pwm_duty[0] = 0; pwm_duty[0] < 256; pwm_duty[0]++) {
                    Set_Pwm_Duty();
               }
           #endif
    }
}




Edit:

Updated code.

Code:
#define directive label was wrong

Pwm_Method_1

was mentioned as Pwm_method_1 with case sensitive turned ON.

Here is the new and final code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#define Pwm_Method_1
 
signed int pwm_duty[2] = {0, 0};
 
void Set_Pwm_Duty() {
    PWM1_Remappable_Set_Duty((unsigned short)pwm_duty[0]);
    
    #ifdef Pwm_Method_1
        PWM2_Remappable_Set_Duty((unsigned short)pwm_duty[1]);
    #else
        PWM2_Remappable_Set_Duty(255 - (unsigned short)pwm_duty[0]);
    #endif
 
    Delay_ms(20);
}
 
void Delay_2Sec() {
    Delay_ms(100);
}
 
void main() {
 
    CM1CON = 0x00;
    CM2CON = 0x00;
    
    CVRCON = 0x00;
    
    ADCON0 = 0x00;
    ADCON1 = 0x80;
    ANCON0 = 0xFF;
    ANCON1 = 0xFF;
    
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
 
    Delay_ms(100);
 
    Unlock_IOLOCK();
    PPS_Mapping_NoLock(0, _OUTPUT, _CCP1_P1A);
    PPS_Mapping_NoLock(1, _OUTPUT, _CCP2_P2A);
    Lock_IOLOCK();
    
    PWM1_Remappable_Init(2000);
    PWM1_Remappable_Set_Duty(0);
    PWM1_Remappable_Start();
    
    PWM2_Remappable_Init(2000);
    PWM2_Remappable_Set_Duty(255);
    PWM2_Remappable_Start();
 
    while(1) {
 
           #ifdef Pwm_Method_1
               for(pwm_duty[0] = 0, pwm_duty[1] = 255; pwm_duty[0] < 256, pwm_duty[1] > 0; pwm_duty[0]++, pwm_duty[1]--) {
                    Set_Pwm_Duty();
               }
               
               Delay_2Sec();
 
               for(pwm_duty[0] = 255, pwm_duty[1] = 0; pwm_duty[0] > 0, pwm_duty[1] < 256; pwm_duty[0]--, pwm_duty[1]++) {
                   Set_Pwm_Duty();
               }
               
               Delay_2Sec();
           #else
               for(pwm_duty[0] = 0; pwm_duty[0] < 256; pwm_duty[0]++) {
                    Set_Pwm_Duty();
               }
               
               Delay_2Sec();
           #endif
    }
}



Use Two_leds - Update A.rar project. In the update 2 sec delay is provided to give good visual effect.

- - - Updated - - -


With pwm_duty > 0 it never goes to negative but with pwm_duty >= 0 it goes to negative as signed int type variable is used.


Edit:

I changed the code a little. Here is the new code. You can take it as final. I have tested it on hardware (PIC Clicker) and it is working fine.

Changes made are:

1. Delay function name changed.
2. Delay value changed
3. Delay function calls positions in code changed to make smaller code. ( I still have to improve my programming skills).

Earlier 3 delay function calls were called. In below code only two calls are called.

Test the Update B project on hardware and reply.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#define Pwm_Method_1
 
signed int pwm_duty[2] = {0, 0};
 
void Set_Pwm_Duty() {
    PWM1_Remappable_Set_Duty((unsigned short)pwm_duty[0]);
    
    #ifdef Pwm_Method_1
        PWM2_Remappable_Set_Duty((unsigned short)pwm_duty[1]);
    #else
        PWM2_Remappable_Set_Duty(255 - (unsigned short)pwm_duty[0]);
    #endif
    
    Delay_ms(20);
}
 
void Variable_Delay() {
    Delay_ms(2000);
}
 
void main() {
 
    CM1CON = 0x00;
    CM2CON = 0x00;
    
    CVRCON = 0x00;
    
    ADCON0 = 0x00;
    ADCON1 = 0x80;
    ANCON0 = 0xFF;
    ANCON1 = 0xFF;
    
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
 
    Delay_ms(100);
 
    Unlock_IOLOCK();
    PPS_Mapping_NoLock(0, _OUTPUT, _CCP1_P1A);
    PPS_Mapping_NoLock(1, _OUTPUT, _CCP2_P2A);
    Lock_IOLOCK();
    
    PWM1_Remappable_Init(2000);
    PWM1_Remappable_Set_Duty(0);
    PWM1_Remappable_Start();
    
    PWM2_Remappable_Init(2000);
    PWM2_Remappable_Set_Duty(255);
    PWM2_Remappable_Start();
 
    while(1) {
 
           #ifdef Pwm_Method_1
               for(pwm_duty[0] = 0, pwm_duty[1] = 255; pwm_duty[0] < 256, pwm_duty[1] > 0; pwm_duty[0]++, pwm_duty[1]--) {
                    Set_Pwm_Duty();
               }
               
               Variable_Delay();
               
               for(pwm_duty[0] = 255, pwm_duty[1] = 0; pwm_duty[0] > 0, pwm_duty[1] < 256; pwm_duty[0]--, pwm_duty[1]++) {
                   Set_Pwm_Duty();
               }
           #else
               for(pwm_duty[0] = 0; pwm_duty[0] < 256; pwm_duty[0]++) {
                    Set_Pwm_Duty();
               }
           #endif
           
           Variable_Delay();
    }
}

 

Attachments

  • Two Leds.rar
    16.2 KB · Views: 78
  • Two Leds - Update A.rar
    16.4 KB · Views: 78
  • Two Leds - Update B.rar
    16.4 KB · Views: 82
Last edited:
Reactions: anim1

    anim1

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…