Society of Robots - Robot Forum

Software => Software => Topic started by: brian on March 02, 2008, 06:03:44 PM

Title: Timing problems
Post by: brian on March 02, 2008, 06:03:44 PM
Hello, right now I am messing around with the 50 dollar robot... however I found an odd problem while programming. I had attempted to control a servo (without using SoRutils as I wanted to learn how to do it for myself). I could (using _delay_ms(1000);) send out a 1ms pulse every 10ms which worked great, the servo moved to the end. The only problem is it would stay in the same position when I sent out a 2ms pulse.

Then I thought the timer might be off, so I began messing around with turning the LED on and off. I found I could get it to blink using _delay_ms. So to test if it was off I used this code...
Code: [Select]
                PORT_OFF(PORTD,4);
_delay_ms(1000);
PORT_ON(PORTD,4);
_delay_ms(1000);

Which worked just fine, however when I counted the blinks over a period of 1 minute I got about 27 blinks (when it should have been 30).

Then I tried delay_cycles and found that the LED would stay on with this code

Code: [Select]
                PORT_OFF(PORTD,4);
for(int x=0;x<222;x++){
delay_cycles(655);
}
PORT_ON(PORTD,4);
for(int x=0;x<222;x++){
delay_cycles(655);
}

I have no idea why delay_cycles doesn't work the way it should. I have tried a variety of values for it but to no avail. Why is this? Also how can I get my code to be timed properly so I can control servos?
Title: Re: Timing problems
Post by: paulstreats on March 02, 2008, 06:19:59 PM
It might be due to the compiler. When you loop code with a for loop or something, this translates into assembly, the for loop assembly code doesnt work out to just 1 programming line usually, so sometimes 1 command in c might produce 4 or5 commands assembly. Its the assembly commands that really count.

As with the servo, any delay command needs to be preconfigured in some way so it knows which clock speed you are using (ie. 4mhz, 8mhz, 16mhz the compiler doeasnt know until you tell it). The fact is that it is probably moving the servo to its furthest extent both times because they are both delaying under the real delay time (because you havent set the clock speed).

If you post up your whole coding, and the setup such as if youre using internal oscillator maybe we can give you a definate sulotion and point you in the right direction :)
Title: Re: Timing problems
Post by: brian on March 02, 2008, 06:25:10 PM
Thanks for the reply! :) I am currently using an atmega8 with an internal oscillator. I have also noticed that the problem happens even when I am not using for loops (I increase the cycles of course).


Code: [Select]
#include <avr/interrupt.h>    // Defines pins, ports, etc to make programs easier to read
#define F_CPU 1000000       // Sets up the default speed for delay.h
#include <util/delay.h>
#define PORT_ON( port_letter, number ) port_letter |= (1<<number)
#define PORT_OFF( port_letter, number ) port_letter &= ~(1<<number)

void delay_cycles(unsigned long int cycles){
while(cycles > 0){
cycles--;
}
}

int main(){


DDRD = _BV(PD4);

while(1){
PORT_ON(PORTD, 4);
delay_cycles(35);
PORT_OFF(PORTD, 4);
delay_cycles(200);
}
return(0);
}
Title: Re: Timing problems
Post by: paulstreats on March 02, 2008, 06:38:47 PM
The first thing that i notice is that you are including the delay.h header file, but in code you are redefining your delays by making a delays function - so youre not actually using the delays in the header file but rather trying to make your own which are timed by clock cycles that you havent predifined yet.

Making your own delays function rely's on using the executing speed of the command and is okay to use but takes a lot of calculating.

Since you are including delays.h , it is worthwhile investigating how to use them (since you set the oscillator speed to work with that and not your own made function). You can open the delays.h header file in a text editor and see how to use its functions, they are likely to be something like delayMs(100) //will delay for 100 ms (it changes depending on what compiler your using).

Title: Re: Timing problems
Post by: brian on March 02, 2008, 06:55:19 PM
Yeah, I have been using _delay_ms(ms); from delay.h ... however I think my F_CPU might be off because it is not accurate. Since it wasn't accurate I tried to use the function delay_cycles to make my own but then I got that odd LED issue.

I believe the atmega8 internal oscillator is 1 megahertz so my F_CPU is correct isn't it?
Title: Re: Timing problems
Post by: paulstreats on March 02, 2008, 07:16:14 PM
Did you need to include these lines

DDRD = 0xFF;  //configure all D ports for output
DDRB = 0xC7;  //configure B ports 0, 1, 2, 6, 7 for output (google search '0b11000111 to hex')

To initialise and set up port d before use. Otherwise the port_on / port_off defines probably wont work properly.

ps. the F_CPU is correct
Title: Re: Timing problems
Post by: brian on March 02, 2008, 09:09:24 PM
That fixed it!  ;D Thanks much for your help.

One thing I have noticed though is that sending a 1ms pulse doesn't bring the servo to full left, and 2ms pulse doesnt bring the servo to full right.

Is it possible it is just my servo? Because these were originally for an RC helecopter.
Title: Re: Timing problems
Post by: paulstreats on March 03, 2008, 04:29:17 AM
quite often, those values only do 45degrees either side of the center, you need to work out the values for 90 degrees yourself.

The rc internal oscillator isnt 100% accurate either so you might not get an exact movement
Title: Re: Timing problems
Post by: yokoma on March 05, 2008, 11:31:23 AM
hi everybody
i am having a problem in using the pic16f877 internal timers (like timer0), would you plz tell me how i can use this timer?(since i am not familiar with assembly,i am using pic basic pro compiler so i need any helpful codes in this format)
Title: Re: Timing problems
Post by: Admin on March 09, 2008, 09:48:23 AM
Quote
Which worked just fine, however when I counted the blinks over a period of 1 minute I got about 27 blinks (when it should have been 30).
Well, this is because the oscillator frequency is dependent on many things:
voltage
in circuit noise
quality of components


Its no atomic clock :P