PDA

View Full Version : How to setup 38kHz PWM with PIC18F1330



flotulopex
- 5th March 2015, 16:40
Hi there,

I'm trying to setup a 38kHz PWM with a PIC18F1330.

My circuit is as simple as possible for tests: a blinking "I'm alive" LED and a 8MHz crystal.

Don't get it...


' Fuses PIC18F1330 for MPASM
@ __CONFIG _CONFIG1H, _OSC_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
@ __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOR_OFF_2L & _BORV_0_2L
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
@ __CONFIG _CONFIG3L, _HPOL_HIGH_3L & _LPOL_HIGH_3L & _PWMPIN_OFF_3L
@ __CONFIG _CONFIG3H, _FLTAMX_RA7_3H & _T1OSCMX_LOW_3H & _MCLRE_OFF_3H
@ __CONFIG _CONFIG4L, _STVREN_ON_4L & _BBSIZ_BB256_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
@ __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L
@ __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
@ __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L
@ __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
@ __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L
@ __CONFIG _CONFIG7H, _EBTRB_OFF_7H

'================================================= =========================
' Main Registers
' 76543210
OSCCON = %00000000 'OSCILLATOR CONTROL REGISTER
OSCTUNE = %00000000 'OSCILLATOR TUNING REGISTER
ADCON0 = %00000000 'A/D CONTROL REGISTER 0
ADCON1 = %00000000 'A/D CONTROL REGISTER 1
ADCON2 = %00000000 'A/D CONTROL REGISTER 2
INTCON = %00000000 'INTERRUPT CONTROL REGISTER
INTCON2 = %00000000 'INTERRUPT CONTROL REGISTER 2
INTCON3 = %00000000 'INTERRUPT CONTROL REGISTER 3
TRISA = %00000000 'Data Direction Control Register (Input/Output)
PORTA = %00000000 'State High (1) or Low (0)
TRISB = %00000000 'Data Direction Control Register (Input/Output)
PORTB = %00000000 'State High (1) or Low (0)

' Set up PWM1 (PORTB.1)
PTPERL = %11111111
PTPERH = %11111111
T0CON = %00000000
T1CON = %01001010
PTCON0 = %00000000 'Postscale 1:1, Fosc/4 Prescale 1:1, Free Running Mode
PTCON1 = %10000000 'Time base in ON, Time base counts up
PWMCON0 = %00010000 'PWM1 enabled
PDC0H = 30 'Duty Cycle control for PWM0/1


DEFINE OSC 8

LED var PORTA.2
'PORTB.1 is PWM1

MAIN:
TOGGLE LED
PAUSE 500
GOTO MAIN

END

What is actually the highest PWM frequency I can get with the 8MHz crystal?

The DS is confusing me a lot :-(

mark_s
- 5th March 2015, 17:35
What is actually the highest PWM frequency I can get with the 8MHz crystal?

The DS is confusing me a lot :-(

Hi

If you look on page 129 of the data sheet. There is a chart of Fosc vs. PWM frequency.
They do not list 8mhz, but the highest 4mhz frequency is 3.9khz. So I guess you can expect
it to be double at 8mhz or 7.8Khz

If you configure the oscillator for 4x HSPLL you could get closer.

8mhz crystal 4x HSPLL - PWM freq = 31.2khz max

Did the PWM output anything, you didn't say?

HenrikOlsson
- 5th March 2015, 18:26
Hi,
If you set PTPER to 51 with the prescaler set to 1:1 and 8MHz clock you'll get a PWM period of 26us which 38461Hz, set it to 52 and you'll get 37736Hz.

Just remember that the resolution won't be 14 or even 10 bits at that PWM frequency and oscillator frequency. Forumla says you'll get 7.7bits which would be a dutycycle value of 0 to 246 or there abouts.

/Henrik.

EDIT: Oh, and the highest frequency possible would be when you set PTPER to 1 which would give you a PWM frequency of 1MHz. The resolution will be 2 bits.

mark_s
- 5th March 2015, 19:04
Henrik,

Thanks for correcting my wrong answer.

flotulopex
- 6th March 2015, 06:10
Thank you.

I'll try this out when I'm back home.


Did the PWM output anything, you didn't say?

Yes, it does work. With the code in my first post, I get a PWM signal around 430Hz (not sure about that frequency right now).

HenrikOlsson
- 6th March 2015, 07:35
Hi,

The PWM Period register has 12 bits of resolution and the PWM period is defined as (PTPER+1) * Prescaler / (Fosc/4)

In your original code you have the prescaler set to 1:1 and you're setting PTPER to 65535 but again, only the low 12 bits are used which equals 4095. Plug that into the formula and you'll get 4096/2000000=0.002048. That's a PWM period of 2.048ms or a frequency of 488.28Hz.

/Henrik.

flotulopex
- 6th March 2015, 15:29
I'm modified my code as follows (in bold) and unfortunately, I doesn't work at all now (now PWM signal).

' Fuses PIC18F1330 for MPASM
@ __CONFIG _CONFIG1H, _OSC_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
@ __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOR_OFF_2L & _BORV_0_2L
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
@ __CONFIG _CONFIG3L, _HPOL_HIGH_3L & _LPOL_HIGH_3L & _PWMPIN_OFF_3L
@ __CONFIG _CONFIG3H, _FLTAMX_RA7_3H & _T1OSCMX_LOW_3H & _MCLRE_OFF_3H
@ __CONFIG _CONFIG4L, _STVREN_ON_4L & _BBSIZ_BB256_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
@ __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L
@ __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
@ __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L
@ __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
@ __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L
@ __CONFIG _CONFIG7H, _EBTRB_OFF_7H

'================================================= =========================
' Main Registers
' 76543210
'OSCCON = %00000000 'OSCILLATOR CONTROL REGISTER
'OSCTUNE = %00000000 'OSCILLATOR TUNING REGISTER
ADCON0 = %00000000 'A/D CONTROL REGISTER 0
ADCON1 = %00000000 'A/D CONTROL REGISTER 1
ADCON2 = %00000000 'A/D CONTROL REGISTER 2
INTCON = %00000000 'INTERRUPT CONTROL REGISTER
INTCON2 = %00000000 'INTERRUPT CONTROL REGISTER 2
INTCON3 = %00000000 'INTERRUPT CONTROL REGISTER 3
TRISA = %00000000 'Data Direction Control Register (Input/Output)
PORTA = %00000000 'State High (1) or Low (0)
TRISB = %00000000 'Data Direction Control Register (Input/Output)
PORTB = %00000000 'State High (1) or Low (0)

' Set up PWM1 (PORTB.1)
T0CON = %00000000
T1CON = %01001010
PTCON0 = %00000000 'Postscale 1:1, Fosc/4 Prescale 1:1, Free Running Mode
PTCON1 = %10000000 'Time base in ON, Time base counts up
PWMCON0 = %00010000 'PWM1 enabled
PDC0H = 30 'Duty Cycle control for PWM0/1
PTMRL = %00000000
PTMRH = %00000000
PTPERL = %00110011 ' = 51
PTPERH = %00000000

DEFINE OSC 8

LED var PORTA.2
'PORTB.1 is PWM1

MAIN:
TOGGLE LED
PAUSE 500
GOTO MAIN

END

HenrikOlsson
- 6th March 2015, 15:42
Hi,
Way to high duty cycle value (7680) try writing 30 to PDC0L instead.

/Henrik.

flotulopex
- 6th March 2015, 16:14
Thanks a lot Henrik.

It works now :)

To get a nice "visual" (= visible on scope) close to 50% duty-cycle, I set PDC0L to 100.

I now have to start to "play" with the formula(s) and registers to change values - I might come back for more questions ;)


' Set up PWM1 (PORTB.1)
T0CON = %00000000
T1CON = %01001010
PTCON0 = %00000000 'Postscale 1:1, Fosc/4 Prescale 1:1, Free Running Mode
PTCON1 = %10000000 'Time base in ON, Time base counts up
PWMCON0 = %00010000 'PWM1 enabled
PDC0L = 100 'Duty Cycle control for PWM0/1
PTMRL = %00000000
PTMRH = %00000000
PTPERL = %00110011 ' = 51
PTPERH = %00000000

Sorry to ask maybe a stupid question but what is the interrest of a PWM "resolution" parameter? I can understand resolution for an incoming analog signal, but PWM is only output as far as I know...

Another thing; look at the pulsed signal, especially at the high state where the signal is kind of rippled. What's wrong here?
7726

HenrikOlsson
- 6th March 2015, 16:43
It's not really a parameter in that sense, it's more like a side effect of the relationship between the oscillator frequency and PWM frequency. The closer they are in relation to each other the less resolution you get - it's just the way it works.

Basically, all it is a counter driven by the oscillator. The PWM period is set by telling a comparator at what count to "start over". If the counter is clocked at 1MHz and you tell it start over at the value 100 then the PWM frequency would be 1000000/100=10000Hz. If you tell it start over at 10000 the PWM frequency becomes 1000Hz and so on. This is what the PTPER value does.

The PWM output is set at the start of the PWM cycle and reset when the counter equals the dutycycle value. Now I Think you can see that when the PWM frequency in the example above is 1000Hz ther resolution will be 10000 "steps" while when the PWM frequency is 10000Hz the resolution will be 100 "steps". It's just the way a digital PWM generator works.

As for your ripple, make sure you have decoupling capacitor(s) as close to the supply pins of the PIC as possible. If the PIC has more than one pair of supply pins make sure they are all connected and properly bypassed.

/Henrik.

flotulopex
- 6th March 2015, 21:14
Thanks Henrik.

I had to use a 4,7µF capacitor to finally get a nice clean signal :)

Thank you for the explanation too. I'll have a go for some tests with the formulas; this is going to be the hardest for me...maths are not really my best friends ;)

Roger

flotulopex
- 7th March 2015, 12:04
So there's where I am now:

Desired freq = 38kHz (PWMperiod = 26,3157µs), crystal (Fosc) 20MHz, prescaler = 1
SEARCHING FOR PTPER (max 4095)

Transform formula:
PWMperiod[µs] = (PTPER+1 * prescaler) / (Fosc / 4)
=> (PTER+1 * prescaler) = PWMperiod * (Fosc / 4)
=> PTPER+1 = (PWMperiod * (Fosc / 4)) / prescaler
(26,3157µs * 5'000'000) / 1 = 131

But how do I calculate the duty-cyle register (PDC0) admitting I'd like to have a 50% value to set?

HenrikOlsson
- 7th March 2015, 12:27
Hi,
There will be aproximately 4 times as many "steps" (+/-3) to the dutycycle value as you set PTPER to. If PTPER is 131 then you'll have 131*4 = 524 steps so to get a a 50% dutycycle you set the dutycycle register to 264 (PDC0H=1, PDC0L=8).

/Henrik.

flotulopex
- 7th March 2015, 12:32
Well, I just found this in the DS:

DS note, page 131:
To get the correct PWM duty cycle, always
multiply the calculated PWM duty cycle
value by four before writing it to the PWM
Duty Cycle registers....

I think this means a "100%" (in my mind, this is a signal always high - not useful but for the theory) duty-cycle value would be:
- PTER * 4 => 130 * 4 => 520

So, for a 50% duty-cycle, the PDC0 value is going to to be:
- 520 * 50% => 260

But, playing with the values, I can see on my scope that the numbers would be more accurate taking in account the PTER+1 (131 instead of 130) value.

Where is the truth?

flotulopex
- 7th March 2015, 12:35
...you were quicker ;)