PDA

View Full Version : 12F683 2 x PWM Outputs



retepsnikrep
- 31st January 2010, 00:45
I'm trying to produce two pwm streams from a single 12F683 chip.

The first is fairly easy, a 20khz (25 or 50%) duty cycle for which i can use the chip pwm pin and module.

The second is much slower 2khz variable between 10-90% duty.

I'll need to use a simple high/low on a standard output pin and then some timming and/interrupts to maintain the second pwm output whilst the program services the rest of it's duties.

Can anyone offer an example or some ideas please?

The rest of the program is very simple, a few high/low outputs and one ADC input (joystick) which will be used to vary the 2khz pwm duty cycle.

The adc etc only needs checking say every 1/10th of a second so most of the chip time can be dedicated to the 2khz pwm.

I could use a second 12F683 and have done in the past but wan't to try and cram it all onto a single chip.

Kamikaze47
- 3rd February 2010, 16:15
DT's software PWM should work:

http://darreltaylor.com/DT_INTS-14/SPWM.html

Mike, K8LH
- 7th February 2010, 14:34
Since the 2-KHz PWM period (500-usecs) and duty cycle interval (50-usecs) is an exact multiple of the 20-KHz PWM period (50-usecs), I don't see why you couldn't use the PWM Timer 2 interrupt to update both PWM streams. That is unless interrupt code overhead becomes a significant portion of the 100 instruction cycles available between interrupts (using an 8-MHz clock).

Please forgive me for the pseudo C example (I don't have PBP).

Regards, Mike


;************************************************* *****************
; // setup PWM for a 50-usec period (8-MHz INTOSC, Timer 2
; // prescale 1:1, and PR2 = 99)
;
; char duty1 = 50; // 20-KHz duty cycle, 25 or 50
; char duty2 = 1; // 2-KHz duty cycle, 1..9 (10%..90%)
; char pwm2 = 9; // preset 2-KHz duty cycle counter
;
; void interrupt() // 50-usec interrupt intervals
; { pir1.TMR2IF = 0; // clear timer 2 interrupt flag
; ccpr1l = duty1; // update PWM1 (20-KHz) duty cycle
; pwm2++; // increment PWM2 period counter
; if(pwm2 == 10) // if end of 500-usec period
; { pwm2 = 0; gpio.1 = 1; // reset counter, turn output "on"
; } //
; if(duty2 == pwm2) // if PWM2 duty cycle match
; gpio.1 = 0; // turn PWM2 output "off"
; } //
;

retepsnikrep
- 7th February 2010, 20:40
Thanks for those good ideas. I'll post some code when I have it on breadboard and tested with scope.

retepsnikrep
- 17th December 2010, 00:13
Just resurecting this thread does Mikes idea below look feasible in PBP running at 8mhz on a 12F683? Can I use DT interrupts on timer 2 IT flag if it is being used by the HPWM module to maintain the 20khz pwm ?

Any other brilliant ideas or code examples?



Since the 2-KHz PWM period (500-usecs) and duty cycle interval (50-usecs) is an exact multiple of the 20-KHz PWM period (50-usecs), I don't see why you couldn't use the PWM Timer 2 interrupt to update both PWM streams. That is unless interrupt code overhead becomes a significant portion of the 100 instruction cycles available between interrupts (using an 8-MHz clock).

Please forgive me for the pseudo C example (I don't have PBP).

Regards, Mike


;************************************************* *****************
; // setup PWM for a 50-usec period (8-MHz INTOSC, Timer 2
; // prescale 1:1, and PR2 = 99)
;
; char duty1 = 50; // 20-KHz duty cycle, 25 or 50
; char duty2 = 1; // 2-KHz duty cycle, 1..9 (10%..90%)
; char pwm2 = 9; // preset 2-KHz duty cycle counter
;
; void interrupt() // 50-usec interrupt intervals
; { pir1.TMR2IF = 0; // clear timer 2 interrupt flag
; ccpr1l = duty1; // update PWM1 (20-KHz) duty cycle
; pwm2++; // increment PWM2 period counter
; if(pwm2 == 10) // if end of 500-usec period
; { pwm2 = 0; gpio.1 = 1; // reset counter, turn output "on"
; } //
; if(duty2 == pwm2) // if PWM2 duty cycle match
; gpio.1 = 0; // turn PWM2 output "off"
; } //
;

Darrel Taylor
- 17th December 2010, 01:38
If you only need 9 steps in your 2Khz PWM (10% each step), then Mikes idea will work just fine.

If you want 80 steps between 10-90%, I think you can use SSPWM ...
http://www.pbpgroup.com/modules/wfsection/article.php?articleid=6

The article lists lower maximum frequencies because it can't get 1% resolution so close to the start and end points. But if you only need 10-90%, it should be OK.

If you plan on using it, I will test it to make sure.
Since this thread was from last February, I have doubts.

retepsnikrep
- 17th December 2010, 03:17
Thanks for the reply. I do plan on doing something with this in due course. My chip will be limited to 8mhz so
can it reach 2khz with the limited clock speed. 80 points resolution would be fine.

Darrel Taylor
- 17th December 2010, 05:32
Thanks for the reply. I do plan on doing something with this in due course.
Great confidence I have now ... NOT!

Oh well, more things to do tomorrow I have ....
Tonight, I do this ...
Next year, you may try it.

4999


DEFINE OSC 8

SPWMpin var GPIO.5 ' Output Pin for SSPWM
INCLUDE "SSPWM.inc" ' include the SSPWM module

;----[Constants]------------------------------------------
HPWMfreq CON 20000
Freq = 2000 ' Set Frequency of SSPWM (word)

;----[Variables]------------------------------------------
HPWMduty VAR BYTE
LastHPWMduty VAR BYTE
SSPWMduty VAR BYTE

;----[Initialize]-----------------------------------------
OSCCON = %01110000 ' 8Mhz
ANSEL = %000011 ' AN0 and AN1 ANALOG
DutyCycle = 10 ' Set Duty Cycle of SSPWM
gosub StartSPWM ' Start SSPWM @ Freq/DutyCycle
HPWM 1, 127, HPWMfreq ' Start 20Khz PWM @ 50%

;----[Main Program Loop]---------------------------------
Main:
ADCIN 0, HPWMduty
ADCIN 1, SSPWMduty

IF HPWMDuty != LastHPWMduty THEN
LastHPWMduty = HPWMDuty
HPWM 1, HPWMDuty, HPWMfreq
ENDIF


DutyCycle = SSPWMduty*80/256+10 ' scale SSPWM dutycycle
gosub SetSPWM ' Change SSPWM DutyCycle
GOTO Main

Dutycycle of the 2Khz is 10% in the image.
Both dutycycles are adjustable from the pots, and works from 10% to 90%, (0 to 100% for the HPWM).

Don't forget to comment the wsave vars not used by the 683 in the .inc file.

Happy Holidays.

retepsnikrep
- 17th December 2010, 15:54
Incredible I was envisaging pages of code! many thanks to Darrel :)

Could you post that Isis code and hex code as i have it and would like to look at the simulation.

Darrel Taylor
- 17th December 2010, 20:35
Could you post that Isis code and hex code...
Here ya go.

retepsnikrep
- 18th December 2010, 16:31
Darrel

Can you tell me the version of issis/proteus you are using i can't load it, my version is 7.4 SP2

Cheers

Darrel Taylor
- 18th December 2010, 16:48
7.8 SP0 (beta)

If your license is up to date, you should be able to run the update manager and get the latest version.

retepsnikrep
- 19th December 2010, 08:30
Back to breadboard then it will cost be a fortune to upgrade suffciently to run it. Thanks anyway.
I only have the picaxe VSM lite software which doesnt support simulating plain pics etc anyway.

retepsnikrep
- 25th January 2011, 11:45
Thanks to all those who helped with this :) i have had this breadboarded and working in my pic on bench today, it works great. What a forum incredible. Now to design my pcb.

retepsnikrep
- 17th February 2011, 19:42
Daryl

I bought Proteus and can now load your program but get 1 error on simulation which says.

"Not Built requires PBPW"

Any ideas?

Darrel Taylor
- 17th February 2011, 20:42
I think I had it pointing to PBPW at the time.
Proteus saves the compiler path in the .dsn file.

Go to ... Source > Add/Remove Source code files..
Change the "Code Generation Tool" drop-down box so it points to your installation. (PBPMPLAB)

retepsnikrep
- 18th February 2011, 07:22
Nope same error :(

Can you post exactly whats in your source code boxes?

Darrel Taylor
- 18th February 2011, 15:26
Here's the way that one was setup. But you should change it to use COF instead of HEX and add the -K# command line option.
And make sure your compiler setup is working with a new design.

5177

retepsnikrep
- 19th February 2011, 07:32
Thanks working now.

retepsnikrep
- 8th March 2011, 04:50
I've upgraded to a 16F88 chip now.

Just a thought, is it possible for SSPWM to use TMR0 instead of TMR1 on the 16F88 bearing in mind my 2khz
PWM requirement with variable 10-90% duty in 1% steps?

I'm not complaining SSPWM works well but freeing up TMR1 would let me use it for my
speedo routine.

Darrel Taylor
- 8th March 2011, 16:33
Well, you could certainly write a program that uses TMR0 to generate frequencies.
But SSPWM will not do it.

It needs a 16-bit timer to meet the published Frequency/Dutycycle range.

alexemil5
- 31st December 2012, 10:29
I am a issue to my code.. It can't resolved. What can I do.. I'll show here my source code boxes then please you help me out .......
I hope this community members can help me.

deodeo
- 3rd January 2013, 13:09
I do not want to make new thread so I will ask here:

Can someone help me with rewriting the code (I do not understand asm - please don't laugh at me:mad:) - I need single channel SPWM fixed 95% duty with 85 Hz from 12F683 to drive LEDs (and perhaps extend their life)?

Many thanks in advance!!!

wdmagic
- 4th January 2013, 01:39
First, Im not going to laugh at you not understanding ASM, I don't either. but your on a forum for pick basic pro, so ASM is almost a moot point. What your wanting to do is only 1 line of code other than your pin setting statements. and is easily available in every pic basic pro manual, and instructional book out there. its probobly under the HPWM code, the 683 is a great chip for that exact code, as thats the same I am using for that purpose except im not driving leds.
You really should try doing a search before posting a question, ive seen this code in the forum, I know im bad about asking questions that are already out there too, but I do try to look up some of the answers first.
Also Dont use others posts to ask a question that doesnt really help that persons post get answered, the post here is how to drive 2 PWM from a 683 chip, as far as I know it cant be done, and it looks like they have went to another chip to solve this. this thread should be on its way to being a dead thread. However if someone keeps adding other info in it keeps it alive and will hinder people that are looking at the article for info, they dont find what their looking for. Go ahead and post a thread with your question, there may be someone out there that needs that direct question answered later on and your thread could help, where the tile of this one would not.

I will answer your question with a direct statement out of an instruction book

HPWM
HPWM Channel, Dutycycle, Frequency
Some PIC microcontrollers have one or more built-in circuits to generate pulse width–modulated
square-wave signals (PWM). For example, PIC16F877 has two PWM Channels. Channel 1 is
known as CCP1 (also PORTC.2) and Channel 2 is known as CCP2 (also PORTC.1).
Dutycycle can vary from 0 to 255 which corresponds to 0% (low all the time) to 100% (high all
the time), respectively. A value of 127 gives 50% duty cycle. The highest Frequency is 32,767 Hz,
and on microcontrollers with two channels, the Frequency must be the same on both channels.
The PWM signal is output from the specified pin continuously in the background while the program
executes other instructions.

In the following example, a 1 kHz, 50% duty cycle PWM signal is generated from Channel 1
(CCP1) of a PIC16F683 type microcontroller:
HPWM 1, 127, 1000

this is copied directly from 30 Projects Using PIC BASIC and PIC BASIC PRO
this book came out in 2006, and is available on Google Books for free.
it pretty much teaches you everything you need to know.

I

deodeo
- 4th January 2013, 07:37
Thank you very much for your answer!

Of course I tried HPWM and I use 30 Projects Using PIC BASIC and PIC BASIC PRO as my Bible in programming, but it cannot give such low frequency as 85 Hz.

Apologies again for posting in thread with other topic, and I know that is annoying to make first post with question… I searched the entire web for tips for that for a long time – and recently found DT SPWM (many thanks for that) where frequencies below 255 Hz are possible. I just didn’t find someone made it with 12F683…
Anyway probably I will find time this weekend to try the code in this thread without changes in PWM, something like that:




DEFINE OSC 8

SPWMpin var GPIO.5 ' Output Pin for SSPWM
INCLUDE "SSPWM.inc" ' include the SSPWM module

;----[Constants]------------------------------------------
;HPWMfreq CON 20000
Freq = 85 ' Set Frequency of SSPWM (word)

;----[Variables]------------------------------------------
;HPWMduty VAR BYTE
;LastHPWMduty VAR BYTE
SSPWMduty VAR BYTE

;----[Initialize]-----------------------------------------
OSCCON = %01110000 ' 8Mhz
;ANSEL = %000011 ' AN0 and AN1 ANALOG
DutyCycle = 10 ' Set Duty Cycle of SSPWM
gosub StartSPWM ' Start SSPWM @ Freq/DutyCycle
;HPWM 1, 127, HPWMfreq ' Start 20Khz PWM @ 50%

;----[Main Program Loop]---------------------------------
Main:
;ADCIN 0, HPWMduty
;ADCIN 1, SSPWMduty

;IF HPWMDuty != LastHPWMduty THEN
;LastHPWMduty = HPWMDuty
;HPWM 1, HPWMDuty, HPWMfreq
; ENDIF


;DutyCycle = SSPWMduty*80/256+10 ' scale SSPWM dutycycle

DutyCycle = 95 ' set 95% nominal SSPWM dutycycle
gosub SetSPWM ' Change SSPWM DutyCycle
GOTO Main



Maybe after all I will not need changes in ASM.

Hebemabo
- 21st July 2021, 12:41
Hi,
I copied the program into Microcode Studio and when I compile it I get
the following errors:

ERROR: Variable wsave3 position request 416 beyond RAM_END 191.
ERROR: Variable wsave2 position request 288 beyond RAM_END 191.

I Googled the errors and searched the forum but cant find an answer.

Please help.
Hebemabo

HenrikOlsson
- 21st July 2021, 17:01
Which program, exactly are you talking about? There are several ones in this thread - is it one of them?
And what PIC are you aiming to use and have you selected that particular one in MicrocodeStudio?

/Henrik.

Hebemabo
- 23rd July 2021, 15:13
Hello Henrik , its the code just before my reply. The one by deodeo.

I am programming a 12F683 using PBPro , Microcode Studio , MPASM and Pickit2.
I have selected 12F683 in MicrocodeStudio.

mark_s
- 23rd July 2021, 18:36
Just like DT's interrupt routines, you some times need to comment out a few lines in the include file

Look inside "SSPWM.inc"




' --- IF any of these three lines cause an error ?? Simply Comment them out to fix the problem ----
wsave1 var byte $A0 SYSTEM ' location for W if in bank1
wsave2 var byte $120 SYSTEM ' location for W if in bank2
wsave3 var byte $1A0 SYSTEM ' location for W if in bank3
' ------------------------------------------------------------------------------

Hebemabo
- 23rd July 2021, 20:20
Thank you very much Mark.