|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
|
|
Thread Tools | Rate Thread | Display Modes |
|
|
|
#1
|
||||
|
||||
|
ATMEGA16 PWM
Ok so here is my problem,
I have a AVR ATMEGA16 uC made by atmel. I have normal timers working but I cannot figure out from the data sheet how to get a PWM output. I have posted on avrfreaks.net but none will post an example code for me. All they do is redirect me to ode that is not for my uC. So i decided since I know a few people on here use them if they could post some very basic example code for me which just includes basic PWM timer operation and to have to code commented so I can look at it and learn from it. The datasheet can be found at: http://www.atmel.com/dyn/resources/p...ts/doc2466.pdf thank you in advanced, John |
|
#2
|
|||
|
|||
|
Re: ATMEGA16 PWM
Here is a pwm module I wrote. It is currently set up for an ATMega8, so the register names may need to be changed slightly, but I have used a version of this code on an ATMega16.
This does direct motor control PWM, 0 - 100%, not RC servo PWM. If that is what you want, you need to adjust the period and limit the range. |
|
#3
|
||||
|
||||
|
Re: ATMEGA16 PWM
Usually from what I have seen for the atmegax series you can use any code from a lower processor on a higher level processor with out changing register names. I don't know if it is true but I guess I can try your code and find out.
What compiler do you use? I am currently running AVR studio-GCC I am going to look at some things but do you think it will be safe to hook the servo up to the STK500. wow....that is above my reading level. If possible seeing as how I am a begginer would you mind commenting some, I mean most of that code. I have never seen the #endif and all those # commands before other than #include and #define Could you possible offer an explanation? Also I need "main.h" and "stdint.h" Last edited by John Gutmann : 06-04-2006 at 23:22. |
|
#4
|
||||
|
||||
|
Re: ATMEGA16 PWM
Quote:
|
|
#5
|
||||
|
||||
|
Re: ATMEGA16 PWM
Quote:
Quote:
Quote:
Quote:
You should look at the register settings this code does, and look at the manual sections for those registers to understand how it uses the timer to do PWM. Then you can write you own code or modify this to do what you want. main.h isn't very much: Code:
#define F_CPU 14745600UL extern int direction; // 1 = right side, -1 = left side (reverse) |
|
#6
|
||||
|
||||
|
Re: ATMEGA16 PWM
If you want to generate a pulswidth of 0 - period (0-100%) I generally used Timer 1 because it has to Output Compare Units (A and B).
The code that I use to set up is in asm, because I'm an assembler junkie. Code:
;Init Timers ;Timer 1 16 bit 2 output compare to drive motors ldi temp,0b10110001 ;Clear OC1A/OC1B on compare match, set at top out TCCR1A,temp ;PWM Phase Correct 8bit ldi temp,0b00000001 ;prescaler is 1 out TCCR1B,temp If you want to control RC servos, which are a PWM wave with the PWM from anywhere from .5 ms to 2.5 ms every ~50 hz (20 ms) then I have a pretty inefficient code, but it gets the job done. BTW this is all using a 16mHz crystal. Code:
;Timer 0 (to call servo routine every 10 ms ldi temp,0b00001101 out TCCR0,temp ;set prescaler to 1024 and clear timer on compare match ldi temp,0b00000010 out TIMSK, temp ;generate an interupt on compare match 16mhz/1024/156=100 hz ldi temp,156 out OCR0, temp ;we want to execute the actual servo subroutine 50 hz, but the timer ;doesnt go that slow, so we call the servo every 100 hz, and only execute ;the code every other call Code:
Servo: ;update servo positions, should call every 20ish ms called by interupt push temp push temp2 in temp, SREG push temp dec ServoSt ;this is to activatre the routine only every other interupt tst ServoSt ;since it is called every 10ms brne Servexit ldi ServoSt, 2 clr ServCoun sbi Servport,Serv1 ; Servport is the port and Serv1 is the pin sbi Servport,Serv2 sbi Servport,Serv3 sbi Servport,Serv4 ; rcall Delay200 ;this is to optomize the range of the servo rcall Delay200 ;to 255, because no servo signal should ever be rcall Delay200 ;less than ~400-600 us ser temp ;this is to execute the below code for 2 ms then leave Serloop: dec ServCoun ;servo counter, is decremented ~ every 7.5 us Ser1: cp ServCoun,Servo1 ;sees if the servo counter is more or = to the brsh Ser2 ;desired servo value cbi Servport,Serv1 nop ;an attempt to make it equal if servo is met or not Ser2: cp ServCoun,Servo2 brsh Ser3 cbi Servport,Serv2 nop Ser3: cp ServCoun,Servo3 brsh Ser4 cbi Servport,Serv3 nop Ser4: cp ServCoun,Servo4 brsh Ser5 cbi Servport,Serv4 nop Ser5: ;continue if more servos rcall Delay7 dec temp brne Serloop ServExit: pop temp out SREG,temp pop temp2 pop temp reti all of the names temp, temp2, Serloop, ServSt, Servo1- 4 are all registers. To change the servo position change the value of Servo1-4. AND one more thing, Delay200, Delay7 are two delay loops. Their code: Code:
Delay7: ; each cycle = 62.5 ns (16 MHz) ; number of processor cycle = 112 = 40 uS ; total delay ~7 useconds ;clr DelayCounter1 ;1 (A) ldi DelayCounter1, 35 ; DelayLoop2: ; dec DelayCounter1 ;60 x 1 (B) brne DelayLoop2 ;1 x 1 if no branch (C), 255 x 2 if branch (D) ; (A) (B) (D) (C) ; so far: 1 + 60 + 118 + 1 = 180 cycles * 62.5ns ; ; 1 + N + (N-1)*2 + 1 = 1 + 3N -2 + 1 = 3N ; N=213 --> 40 uS ret Delay200: ldi DelayCounterMS, 5 ;40*5=200 useconds Delay200msloop: call Delay40 dec DelayCounterMS brne Delay200msloop ret Code:
Delay40: ; each cycle = 62.5 ns (16 MHz) ; number of cycle = 213 = 40 uS (not processor cycles) ; total delay 40 useconds (slightly less) ;clr DelayCounter1 ;1 (A) ldi DelayCounter1, 210 ;1 (was 213, 210 tuned with Locic Analy) DelayLoop1: ; dec DelayCounter1 ;256 x 1 (B) brne DelayLoop1 ;1 x 1 if no branch (C), 255 x 2 if branch (D) ; (A) (B) (D) (C) ; so far: 1 + 256 + 510 + 1 = 768 cycles * 270 ns --> 207 useconds ; 768 * 62.5 --> 48 useconds ; 1 + N + (N-1)*2 + 1 = 1 + 3N -2 + 1 = 3N ; N=213 --> 40 uS ret [Edit for code tags, thanks Matt Krass] Last edited by intellec7 : 12-04-2006 at 13:54. |
|
#7
|
||||
|
||||
|
Re: ATMEGA16 PWM
Quote:
Might I recommend the use of [ code] and [ /code] tags? Code:
;Init Timers ;Timer 1 16 bit 2 output compare to drive motors ldi temp,0b10110001 ;Clear OC1A/OC1B on compare match, set at top out TCCR1A,temp ;PWM Phase Correct 8bit ldi temp,0b00000001 ;prescaler is 1 out TCCR1B,temp The way I have it, it does not generate interupts, the Atmega hardware has two pins, OC1A and OC1B, this allows you to do 16 bit pwm on two channels. If you want to control RC servos, which are a PWM wave with the PWM from anywhere from .5 ms to 2.5 ms every ~50 hz (20 ms) then I have a pretty inefficient code, but it gets the job done. BTW this is all using a 16mHz crystal. ;Timer 0 (to call servo routine every 10 ms ldi temp,0b00001101 out TCCR0,temp ;set prescaler to 1024 and clear timer on compare match ldi temp,0b00000010 out TIMSK, temp ;generate an interupt on compare match 16mhz/1024/156=100 hz ldi temp,156 out OCR0, temp ;we want to execute the actual servo subroutine 50 hz, but the timer ;doesnt go that slow, so we call the servo every 100 hz, and only execute ;the code every other call I first have a timer that calls an adress every 10 ms, but in the actual subroutine it only executes the code every even call. Servo: ;update servo positions, should call every 20ish ms called by interupt push temp push temp2 in temp, SREG push temp dec ServoSt ;this is to activatre the routine only every other interupt tst ServoSt ;since it is called every 10ms brne Servexit ldi ServoSt, 2 clr ServCoun sbi Servport,Serv1 ; Servport is the port and Serv1 is the pin sbi Servport,Serv2 sbi Servport,Serv3 sbi Servport,Serv4 ; rcall Delay200 ;this is to optomize the range of the servo rcall Delay200 ;to 255, because no servo signal should ever be rcall Delay200 ;less than ~400-600 us ser temp ;this is to execute the below code for 2 ms then leave Serloop: dec ServCoun ;servo counter, is decremented ~ every 7.5 us Ser1: cp ServCoun,Servo1 ;sees if the servo counter is more or = to the brsh Ser2 ;desired servo value cbi Servport,Serv1 nop ;an attempt to make it equal if servo is met or not Ser2: cp ServCoun,Servo2 brsh Ser3 cbi Servport,Serv2 nop Ser3: cp ServCoun,Servo3 brsh Ser4 cbi Servport,Serv3 nop Ser4: cp ServCoun,Servo4 brsh Ser5 cbi Servport,Serv4 nop Ser5: ;continue if more servos rcall Delay7 dec temp brne Serloop ServExit: pop temp out SREG,temp pop temp2 pop temp reti Code:
Delay7: ; each cycle = 62.5 ns (16 MHz) ; number of processor cycle = 112 = 40 uS ; total delay ~7 useconds ;clr DelayCounter1 ;1 (A) ldi DelayCounter1, 35 ; DelayLoop2: ; dec DelayCounter1 ;60 x 1 (B) brne DelayLoop2 ;1 x 1 if no branch (C), 255 x 2 if branch (D) ; (A) (B) (D) (C) ; so far: 1 + 60 + 118 + 1 = 180 cycles * 62.5ns ; ; 1 + N + (N-1)*2 + 1 = 1 + 3N -2 + 1 = 3N ; N=213 --> 40 uS ret Delay200: ldi DelayCounterMS, 5 ;40*5=200 useconds Delay200msloop: call Delay40 dec DelayCounterMS brne Delay200msloop ret (note Delay200 depends on Delay40!!) Delay40: ; each cycle = 62.5 ns (16 MHz) ; number of cycle = 213 = 40 uS (not processor cycles) ; total delay 40 useconds (slightly less) ;clr DelayCounter1 ;1 (A) ldi DelayCounter1, 210 ;1 (was 213, 210 tuned with Locic Analy) DelayLoop1: ; dec DelayCounter1 ;256 x 1 (B) brne DelayLoop1 ;1 x 1 if no branch (C), 255 x 2 if branch (D) ; (A) (B) (D) (C) ; so far: 1 + 256 + 510 + 1 = 768 cycles * 270 ns --> 207 useconds ; 768 * 62.5 --> 48 useconds ; 1 + N + (N-1)*2 + 1 = 1 + 3N -2 + 1 = 3N ; N=213 --> 40 uS ret |
|
#8
|
||||
|
||||
|
Re: ATMEGA16 PWM
Do you happen to have anything in C? Just a quick and easy code that will show me how to do it.
What should my timer be set at? 8mhz I am guess to get the most efficient use of your processor. What Timer should I use? What is the easiest way to run 2 servos at once? |
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| reading hobby PWM | sciguy125 | Programming | 2 | 17-10-2005 20:47 |
| FYI about using PWM 13-16 with interrupts | cabbagekid2 | Programming | 6 | 22-01-2005 00:54 |
| Using an Operator Interface with the 2004 EDU RC wirelessly | Dave Flowerday | Robotics Education and Curriculum | 34 | 19-04-2004 19:06 |
| pwm 13-15 | wayne 05 | Programming | 2 | 04-10-2003 12:08 |
| PWM and burning out motors | patrickrd | Technical Discussion | 7 | 19-06-2003 15:30 |