Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[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.
wp_20141102_13_32_37_pro.jpg

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
 

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 ?

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: 114

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

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

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: 106

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:

0
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 77 78 79 80
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255


255 254 253 252 251 250 249 248 247 246 245 244 243 242 241 240
239 238 237 236 235 234 233 232 231 230 229 228 227 226 225 224
223 222 221 220 219 218 217 216 215 214 213 212 211 210 209 208
207 206 205 204 203 202 201 200 199 198 197 196 195 194 193 192
191 190 189 188 187 186 185 184 183 182 181 180 179 178 177 176
175 174 173 172 171 170 169 168 167 166 165 164 163 162 161 160
159 158 157 156 155 154 153 152 151 150 149 148 147 146 145 144
143 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128
127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112
111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96
95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80
79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64
63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
65535 65534 65533 65532 65531 65530 65529 65528 65527 65526 65525 65524 65523 65522 65521 65520
65519 65518 65517 65516 65515 65514 65513 65512 65511 65510 65509 65508 65507 65506 65505 65504
65503 65502 65501 65500 65499 65498 65497 65496 65495 65494 65493 65492 65491 65490 65489 65488
65487 65486 65485 65484 65483 65482 65481 65480 65479 65478 65477 65476 65475 65474 65473 65472
65471 65470 65469 65468 65467 65466 65465 65464 65463 65462 65461 65460 65459 65458 65457 65456
65455 65454 65453 65452 65451 65450 65449 65448 65


:???: 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 - - -

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 ..

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: 74
  • Two Leds - Update A.rar
    16.4 KB · Views: 75
  • Two Leds - Update B.rar
    16.4 KB · Views: 78
Last edited:
  • Like
Reactions: anim1

    anim1

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top