Society of Robots - Robot Forum
Software => Software => Topic started by: mo2000xj on April 30, 2008, 11:17:03 AM
-
I am using an atmega128 and trying to drive a servo using pwm. I am getting a signal coming out, but not the right signal. I think I'm missing the OC1 function which brings the frequency to a lower hz output. I may need a prescaler also. The frequency I have coming out is 800 hz and a micro second plulse instead of a millisecond pulse. The servo requires the usual 1, 1.5, and 2 ms pulse. I am sending my code. I am using assembly language to form the program, and I got ideas for this code on avrfreaks.
;===========================
;Declarations
;===========================
.device ATmega128
.org 0 ;start at 0
rjmp reset
.def Temp = r26 ;temporary register
RESET:
ldi r16, low(RAMEND) ;init low end stack
ldi r17, high(RAMEND) ;init high end stack
out SPL, r16
out SPH, r17
sbi ddrb,PB6 ;sets bits in I/O register
;non-inverting fast PWM mode, no clock prescaling
ldi temp, 0b10100000 ;COM1B1+WGM11+WGM10
out tccr1a, temp
ldi temp, 0b00010010 ;WGM13+WGM12+CS10
out tccr1b, temp
;total period = 20ms
ldi temp, 0x4E
out ocr1ah, temp ;msb
ldi temp, 0x20
out ocr1al, temp ;lsb
;pulse length = 1.5ms
ldi temp, 0x05
out ocr1bh, temp ;msb
ldi temp, 0xDC
out ocr1bl, temp ;lsb
loop:
rjmp loop
-
I'm using Timer 3 and C code, but this may give you some ideas, I'm also running it at 16Mhz.
-
try using the frequency and phase correction mode of the timers if you need some code example in C i can help you
-
This post may help. The link it gives at the end is also useful.
http://www.societyofrobots.com/robotforum/index.php?topic=1827.msg12082#msg12082 (http://www.societyofrobots.com/robotforum/index.php?topic=1827.msg12082#msg12082)
-
the easiest way is to do the following:
timer1 (16 bit) workin at (fast pwm mode with top=ICR1)
you set ICR1 to 20000
timer's triggering clock is 1MHZ = 8MHZ/8
this way you got a frequency of 50 hz which is greta for servos
and the ocr is set to exactly what you want the high pulse to be
let ssay we want to center the servo
all u do is
OCR1=1500;
-
isnt phase and frequency correct mode better than fast pwm
-
snt phase and frequency correct mode better than fast pwm
????? better?? why?
read my post,, anything weak or hard to do?
-
well they are basically the same but in some respects phase and frequency correct mode is better than fast pwm
-
phase and frequency correct mode is better than fast pwm
can u explain?
-
You guys have given me good ideas so far. I'm looking at what Benji wrote about the OCR1 timer. I'm getting some great feedback and I'm hoping to figure out to configure that into the program.
-
i dont know the exact reading but i read it somewhere in the internet it has something to do with the fact that in phase and frequency correct mode the timer goes up and then down.. something to do with high resolution
-
,, no u dont get higher resolution , you get longer pulses ,which means less freqs
,your timer clocking source is the same .
and by the way the resolution i did provide by the mode i suggested is 1/20000
which means 1 uS as LSB
this is very small that the servo wont recognize a single lsb change
which provides the smoothest servo motion
-
may be ill try ur method and see if its better
-
Is there a way to configure the OCR1 timer into the program that I already have? The phase and frequency mode looks very interesting as well, but maybe that won't work so well with this application, or will it? If the OCR1 timer is to be set to 1500, where would I place that? Would it be where I initialize the bits?
-
Phase (and frequency) correct modes operate on a dual slope. You get half the speed and double the smoothness (but only if controlling two motors).
Phase correct might be less useful for a servo application.
-
are u sure fast pwm is better?
-
its not a matter of being better,, its a matter of what u want to do,,
to move a servo you just need to move it as smooth as you can
plus .. the option on making ICR as top is great to make 20ms pulses as you set ICR to 20000 with a freq of 1Mhz as the timer trigger
this way seems perfect,,with great precision
phase correct just double count the timer,so this gives you wider pulses
this is not needed in servos
mo2000xj ,,what do you want to do ? center the servo?
in order to do so you have to provide a PWM of 1500uS (high logic) (20ms whole pulse time == 50hz freq)
so you should give the OCR the number of 1500 decimal
ocr1 = 1500;
while(1)
{};
thats it
-
Benji and to the others, I'm sorry I didn't specify what I wanted the servo to do. I am trying to allow the servo to first be centered for a certain period of time, say 5 seconds, then move to the counter-clockwise direction for 5 seconds, then clockwise for 5 seconds, finally center again. I'm getting a microsecond signal coming from the PWM on pin PB6 on the oscilloscope instead of the millisecond signal I was wanting. I believe it has to do with what Benji mentioned on the OCR1 and ICR1 being set. The frequency on the oscilloscope was reading 800 Hz. The program above is a start, but I know I'll have to add counters in with the timing to have it stay in a loop for a certain amount of time and then jump when the register increments. When the whole program is done, I want it to rjmp and loop to the top and start over. I wish I knew more about C language. The university I'm going to had us start becoming familiar with assembly language, so C is a little different, but I can still see where I can convert. A good site I found that I have been looking at today for timing on avr boards is this: http://www.avrbeginners.net/architecture/timers/timers.html#pwm_mode
-
here i did initialize the timer 1
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1000.000 kHz
// Mode: Fast PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Discon.
// OC1C output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
// Compare C Match Interrupt: Off
TCCR1A=0x82;
TCCR1B=0x1A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x4E;
ICR1L=0x20;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
OCR1CH=0x00;
OCR1CL=0x00;
after you intialize you do the following
OCR1A=1500; //DECIMAL
this piece of code is just to center your servo
so you dont need no loops,, its just a matter of setting the OCRA1 to give stable pulses
which is in this case has a fre of 50hz and a high logic width of 1500uSec
now to turn your servo to the right, lets say we should provide it a highlogic of 2400 uS as width
so you do the folowing
OCR1A=2400;
when the processor come to this operation it starts to provide the pwm wanted and the servo starts to move
then you should calculate the time need for the servo to reach the final destination
and add it as a delay
to do more delay(5 secs)
you just need to add a delay loop that lasts for 5 secs,,easy...
now if you meant somthing else,,maybe you want the servo to take 5 secs to reach the final destination?do you want to slow it down?
there you go
while( OCR1A < 2400)
{
OCR1A++;
delay_ms(55);
}
now u wonder where the heck did this 55ms came from,,let me tell ya
(5000000us) / (2400us-1500us) == 55ms
whichi is
total delay wanted / number of loop iterations
so this while loop is gonna last for 5 seconds and when its over the servo would have reached the final destination (right)
a delay of 55ms between increments is not notices so the motion is pretty smooth
great job for a 5 seconds (very slow)
-
I wish I knew more about C language. The university I'm going to had us start becoming familiar with assembly language, so C is a little different,
if you get dirty with robotics you need C ,, even in my university they teach us 8051 assembly only
do learn by yourself, C aint that hard, a good book would do it
-
it isn't hard if u have a good understanding for programming concepts and logic but yes it is very vast
-
Will the C code work in the AVR compiler? I believe it has a "avr assembler" and a "gcc compiler" when you first start writing the program.
-
its the gcc compiler
-
I'm using Timer 3 and C code, but this may give you some ideas, I'm also running it at 16Mhz.
unable to download the attachment :(
getting the error message : 404 - Attachment Not Found