Creating PWM Using Microcontrollers

thatoneguy

Joined Feb 19, 2009
6,359
I don't know assembly, as I have had no experience in that regard. Perhaps you can make one using the algorithms I provided?
You could direct your C Compiler to output the .asm file. It would be a start for most, as it keeps the comments of the C program, in addition to the commands that created each assembler line.

The variables usually aren't meaningfully named, and the way memory management is handled is a bit odd from an asm programmers viewpoint, but it would be translatable.

I don't know why so many stay with assembly on the PIC when there are great C compilers out there for free. Sourceboost creates tighter code than most new to assembly can code by hand.
 

jpanhalt

Joined Jan 18, 2008
11,087
I don't know why so many stay with assembly on the PIC when there are great C compilers out there for free. Sourceboost creates tighter code than most new to assembly can code by hand.
Not everyone starts with the 18F series. I am still learning with the 12F. For that processor, Assembly works great.

My last coding experience before trying microcontrollers was with Basic and numbered lines (circa 1980). Assembly was far easier and quicker for me to get into for simple projects than learning a higher level language.

What is your recommendation for a free C compiler that is not severely constrained?

John
 

thatoneguy

Joined Feb 19, 2009
6,359
Not everyone starts with the 18F series. I am still learning with the 12F. For that processor, Assembly works great.

My last coding experience before trying microcontrollers was with Basic and numbered lines (circa 1980). Assembly was far easier and quicker for me to get into for simple projects than learning a higher level language.

What is your recommendation for a free C compiler that is not severely constrained?

John
SourceBoost C Or SourceBoost Basic

The limitations are in the links above. Rather generous for the free one, and $70 for no limits, but non-commercial uses. If you will be selling the code you write, the license price doubles. Even then, it is cheaper than most other compilers around at $150 for the C compiler, Real Time Operating System with source code, and source code for all the libraries.
 

Potato Pudding

Joined Jun 11, 2010
688
The Enhanced Capture/Compare/PWM module is a
peripheral which allows the user to time and control
different events. In Capture mode, the peripheral
allows the timing of the duration of an event. The
Compare mode allows the user to trigger an external
event when a predetermined amount of time has
expired. The PWM mode can generate a Pulse-Width
Modulated signal of varying frequency and duty cycle.
Table 11-1 shows the timer resources required by the
ECCP module. from PIC16f88X datasheet
This is a standard feature of many PIC's.

Microchip is all over this requirement. I didn't see many references and there are resources all over the Microchip website.

Like this PDF

You might want to look at some of their application notes like

AN538 and just for interest AN771.

They talk about motor control and usage for D/A conversion

They have specific PWM controllers like the TC105 step down voltage conversion controller with frequency as well as width modulation which should allow lower idle currents. Specific devices can be better and simpler than using a PIC. There are other manufacturers that should be looked at but even Microchip would say "This is the way we would do PWM for this purpose and it isn't a PIC".

I think this topic is great but I just want it to be clear that this is slightly marginal in terms of real applications.

If you don't have a PIC with CCP and want to do PWM then my first choice would to look at other IC's or PICs instead of reinventing everything and loading my PIC with this type of code as overhead.

Showing that it is possible to do some PWM with only code and standard PIC I/O pins is still awesome.
 

MMcLaren

Joined Feb 14, 2010
861
.... What is your recommendation for a free C compiler that is not severely constrained?
I would also recommend the free/lite version of BoostC, John. The limitations are such that you have no limitation on code space for the 12F683 but you're limited to two banks of RAM.

I like that I can run it within MPLAB.

Regards, Mike
 

Thread Starter

ELECTRONERD

Joined May 26, 2009
1,147
Not everyone starts with the 18F series. I am still learning with the 12F. For that processor, Assembly works great.

My last coding experience before trying microcontrollers was with Basic and numbered lines (circa 1980). Assembly was far easier and quicker for me to get into for simple projects than learning a higher level language.

What is your recommendation for a free C compiler that is not severely constrained?

John
Assembly works great if you know it, but most C compilers allow a tighter code fit for those who don't. I am thinking of learning assembly myself, how did you go about it with the PIC MCU's?
 

jpanhalt

Joined Jan 18, 2008
11,087
Assembly works great if you know it, but most C compilers allow a tighter code fit for those who don't. I am thinking of learning assembly myself, how did you go about it with the PIC MCU's?
Quite literally, I installed MPLab. Went through an example from the instruction book (version 5.3 or thereabouts), and never needed anything more. Obviously, getting into things like DSP requires a higher level language, but for controlling servos, PWM, reading IR detectors, and simple serial communications (see my project using SPI in the Completed Projects Forum), Assembly works great.

I do plan to take the suggestions for C compilers seriously ($70 is almost free) and in all likelihood will start using that language for more complicated projects. I suspect I will always appreciate the ability to include an Assembly routine within a C program, though. I was one of the last people to convert from DOS to Windows in my department. I do like to know what is really going on. It's a control thing, I guess. :D

John
 

Thread Starter

ELECTRONERD

Joined May 26, 2009
1,147
Can you do the same with an Arduino Uno to be able to use more than 6 outputs as PWM outputs?
Hi mikeysela,

I think it might be possible. Are you trying to control six outputs with one PWM signal, or are you trying to control six outputs as individual PWM signals? I've been able to drive many outputs at once, just specify the number of pins; 0x0F, for instance, would utilize four outputs. Or you can list the function many times for each of the PWM outputs to obtain individual PWM signals.
 

Tahmid

Joined Jul 2, 2008
343
Hi,
I wanted to add this for someone who might find it useful. It's in asm and with PIC16F877A. lloydi12345, you can take a look at this.

Rich (BB code):
; SOURCE CODE FOR DC MOTOR CONTROL WITH PIC16F877A
; -------------------------------------------------

; PREPARED BY-- SYED TAHMID MAHBUB 

; DATED-- 21-04-09  

;---------------------------------------------------------------

    TITLE: "DC MOTOR CONTROL WITH PIC 16F877A"  
        
        LIST   P=16F877A

       INCLUDE "P16F877A.INC"

       __CONFIG    H'3F72'

     ; __CONFIG _HS_OSC & _WDG_OFF & _PWRTE_ON & _CP_OFF

     ; 10 MHZ EXTERNAL CRYSTAL OSCILLATOR.    
     
;----------------- PROGRAM START -------------------------------------


           ORG     0X00          ; RESET VECTOR
           GOTO    INIT
           ORG     0X04          ; INTERRUPT VECTOR
           GOTO    INTR_SVC   

;------------------ INITIAL PROCESS ------------------------------

;-- PORT INITIALIZATION

INIT
           BSF      STATUS,RP0    ; CHANGE TO BANK 1
           MOVLW    B'00000001'   ; AN0 TO INPUT MODE
           MOVWF    TRISA         ; SET TRISA REGISTER
           CLRF     TRISC         ; MAKING PORTC ALL OUTPUT
           BCF      STATUS,RP0    ; CHANGE TO BANK0


;--- A/D CONVERTER INITIALIZATION 

           MOVLW    B'10000001'   ; FOSC/32,RA0/AN0,ADON=ON
           MOVWF    ADCON0        ; SET ADCON0 REGISTER
           BSF      STATUS,RP0    ; CHANGE TO BANK 1
           MOVLW    B'00001110'   ; ADFM=0,PCFG=1110
           MOVWF    ADCON1        ; SET ADCON1 REGISTER,IN BANK 1
           BCF      STATUS,RP0    ; FALLING BACK TO BANK 0

;--- PWM  INITIALIZATION 

           CLRF     TMR2          ; CLEAR TMR2 REGISTER
           CLRF     CCPR1L        ; CLEAR CCPR1L REGISTER
           BSF      STATUS,RP0    ; CHANGE TO BANK 1
           MOVLW    D'255'        ; PERIOD = 1638.4USEC(610 HZ)
           MOVWF    PR2           ; SET PR2 REGISTER,IN BANK 1
           BCF      STATUS,RP0    ; CHANGE TO BANK 0
           MOVLW    B'00000110'   ; PST=1:1,TMR1=ON,PRE=1:16
           MOVWF    T2CON         ; SET T2CON REGISTER
           MOVLW    B'00001100'   ; CCP1XY=0,CCP1M=1100(PWM)
           MOVWF    CCP1CON       ; SET CCP1CON REGISTER

;--- COMPARE MODE INITIALIZATION 

           CLRF     TMR1H         ; CLEAR TMR1H REGISTER
           CLRF     TMR1L         ; CLEAR TMR1L REGISTER
           MOVLW    0X09          ; H '9C4'=2500
           MOVWF    CCPR2H        ; SET CCPR2H REGISTER
           MOVLW    0XC4          ; 2500 X 0.4 uSEC = 1MSEC
           MOVWF    CCPR2L        ; SET CCPR2L REGISTER
           MOVLW    B'00000001'   ; TMR1= ON
           MOVWF    T1CON         ; SET T1 REGISTER
           MOVLW    B'00001011'   ; SET SPECIAL TRIGGER FOR A/D CONVERSION
           MOVWF    CCP2CON       ; SET CCP2CON REGISTER

;---INTERRUPTION  CONTROL

           BSF      STATUS,RP0
           MOVLW    B'00000001'   ; CCP2IE = ENABLE
           MOVWF    PIE2          ; SET PIE2 REGISTER
           BCF      STATUS,RP0
           MOVLW    B'11000000'   ; GIE = ON, PEIE = ON
           MOVWF    INTCON        ; SET INTCON REGISTER

WAIT
           GOTO     $             ; WAIT FOR INTERRUPTION

;------------------- INTERRUPTION  PROCESS --------------------------
INTR_SVC
           CLRF     PIR2          ; CLEAR INTERRUPTION FLAG
AD_CHECK  
           BTFSC    ADCON0,GO     ; A/D CONVERT END?
           GOTO     AD_CHECK      ; NO.CHECK AGAIN
           MOVF     ADRESH,W      ; READ ADRESH REGISTER
           MOVWF    CCPR1L       ; RESET DUTY CYCLE OF PWM
           RETFIE

;------------------- END OF INTERRUPTION PROCESS ---------------------

           END


;--------------------------------------------------------------------
;                   END OF THE MOTOR CONTROL PROCESS
;--------------------------------------------------------------------
It's commented so that it's easy to understand.

Hope this helps.
Tahmid.
 

mikeysela

Joined Jul 24, 2010
87
Hi mikeysela,

I think it might be possible. Are you trying to control six outputs with one PWM signal, or are you trying to control six outputs as individual PWM signals? I've been able to drive many outputs at once, just specify the number of pins; 0x0F, for instance, would utilize four outputs. Or you can list the function many times for each of the PWM outputs to obtain individual PWM signals.
Hi Electronode.

I am trying six or more (trying to control more) outputs as six or more individual PWM signals. I know the arduino can outputs 6 different PWM signals using its analogWrite function, but that is only made simple with 6 of the digital outputs of an arduino. I am hoping to find out if I can write some code to create PWM signal for the digital I/O pins that dont have built in PWM capability.
 

Tahmid

Joined Jul 2, 2008
343
Hi mikeysela,
Since you talk about Arduino Uno, the controller is ATMEGA328. I don't know which language or compiler you use, but it's quite simple. I don't know much about the Arduino, but I can help you go through the coding in mikroBASIC or mikroC:

1) Have your compare modules set to 0 - normal operation in CTC mode, interrupt on compare OC1A and OC1B.
2) Set mode to 4 - CTC with TOP = OCR1A. Calculate the value required for OCR1A for your specific frequency:

3) Then set OCR1B for duty cycle:
Rich (BB code):
DC = (OCR1B/OCR1A) * 100%
4) Then enable interrupts, by setting OCIE1A and OCIE1B and SREG_I bits.
5) Wait for interrupt.
6) In OCIE1B ISR:
Turn on digital-IO-pin.
Return
7) In OCIE1A ISR:
Turn off digital-IO-pin
Return

Hope this helps.
Tahmid.
 

Tahmid

Joined Jul 2, 2008
343
fOCn here is fOC1 which is your desired frequency
fclk_IO is the ATMEGA clock frequency
N is the timer prescaler
OCRn here is OCR1A which is your timer TOP value, that dictates the frequency
DC is the duty cycle expressed in percentage

Above here, I use OCR1A, OCR1B, OCIE1A, OCIE1B as I refer to Timer1.

Hope this helps.
Tahmid.
 

mikeysela

Joined Jul 24, 2010
87
Hi Tahmid,

Thank you very much for that. I actually do not have the Arduino yet, and will wait to make sure I can actually get more than 6 PWM outputs from it until I purchase it. I have saved your code on a document and will definitely try to implement it once I get the Arduino Uno. In general, do you think its possible to create PWM outputs from all digital pins with most of these known microcontrollers? (PIC, AVR, ATMega, etc)

Thank you very much again for your help.

Michael
 

Tahmid

Joined Jul 2, 2008
343
Hi,
Well, it depends on how many you want. What I posted uses the compare module. Since compare modules are limited on these microcontrollers, you won't be getting that much. It's possible, but requires huge coding. If you require more, look at ATMEGA1280. It has 12 modules with resolution from 2 to 16 bit. And 16-bit means true 16-bit, and there are 4 8-bit modules, 7 timers.
And just for the information, ATMEGA is part of the AVR lineup.

Point: It's possible but difficult to implement as there is a need of heavy coding as timer and/or compare modules are limited.

Hope this helps.
Tahmid.
 

mikeysela

Joined Jul 24, 2010
87
Hi Tahmid.

Thanks again for the reply.

I found this article: http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM and it seems to imply that you can use any output from a AtMega328 as a PWM output. Am i misunderstanding it? I think 6 of them use the analogWrite function, but you can manually set any output to be PWM using this article. look specifically at at section Bit-banging Pulse Width Modulation.

I am new to micrcontroller and would like to purchase one that can give me more than 6 PWM outputs, but the selection is so great. I think I prefer to stick to an Arduino since its ease. The arduino Mega is at AtMega2560, but it is also twice as expensive.

Also, thanks for making it clear that AtMega is part of the AVR lineup.

Michael
 

Tahmid

Joined Jul 2, 2008
343
Hi,
Yes you can. One method is:
Rich (BB code):
Start:
   Turn on
   Wait specific time
   Turn off
   Wait specific time
   Goto Start
eg.
Rich (BB code):
Start:
   PIN = 1
   delay_us(10)
   PIN = 0
   delay_us(10)
   Goto Start
That's 50%. So, you can adjust the delays and have PWM. Or you can use my method. What I suggested limits you for peripherals, but lets you multitask, since it only works through interrupts. The other suggested method works for any pin, however, you can do anything while doing the work, well, you can but not with simple delays, but with timer delays, which would again limit you.

Yes, you can, again through some good amount of coding.

Hope this helps.
Tahmid.
 
Top