Society of Robots - Robot Forum
Electronics => Electronics => Topic started by: rox2007 on January 18, 2008, 10:11:38 AM
-
Once again, please help, please
-
u only have a chip? or a whole controll board?
if u have a controll board then search internet for how to make a circuit board with your atmega as its brain and then you can connect ur servos there.
else if u have a control board then where is the problem? just connect the servos where needed and programme it and you are all done :)
but if u know all the hardware thing(like where to connect it and stuff) and you have done this all (like connecting and powering servo) but you only have problems with servo control code, then you should read some examples of servo controll and read tutorials about controlling the servo with the code you want to use.
anyway internet is a good friend of yours :) use it
-
Can you tell us what you have working and what isn't working?
The $50 Robot will tell you exactly how to do it.
Are you sure you have 16MHz?
-
Well, this is what i have done.
--i have my mcu board which runs my line detecting code
--i modified my servo for continuous rotation using the admin tutorial. it worked. servo stopped at 1.5ms
this is what i used for delay
courtesy sparkfun blink_iMhz code
//General short delays
void delay_ms(uint16_t x)
{
uint8_t y, z;
for ( ; x > 0 ; x--){
for ( y = 0 ; y < 90 ; y++){
for ( z = 0 ; z < 6 ; z++){
asm volatile ("nop");
}
}
}
}
--but i added an oscillator t(16mhz and set the fuse bits) to my mcu after . my code ran perfectly but faster, which is what i wanted
--but now when i try to control the servo with 1.5ms using the above code, it doesnt stop instead it moves slower
--so if anyone can help me with a servo control code, i'll be really grateful
-
actually it reverses when it gets that 1.5ms
maybe it recaliberated itself
i should probably run a code from 0ms to 2ms to find the new stop point
-
perhaps when you added on the 16mhz oscillator you messed up the pulse.
A program that controls a servo @ 4mhz will not work correctly control a servo @ 16mhz
But that is based on my experience in assembly and BASIC , though not in C , thats just a guess.
-
yeh, i guess so
i'll just run a code that runs the servo from 0ms to 2ms, and find that centerpoint
-
check you F_CPU settings make sure you've set it up properly for the new oscillator, then don't forget to recompile your code.
-
at what oscillator speed did the servo work correctly?
-
at 4mhz i think
-
check you F_CPU settings make sure you've set it up properly for the new oscillator, then don't forget to recompile your code.
where do i find this
-
check you F_CPU settings make sure you've set it up properly for the new oscillator, then don't forget to recompile your code.
where do i find this
it should be a define in one of your source or header files.
you should find something like:
// make sure the following is the CPU frequency in Hertz
#define F_CPU 1600000UL
in your code.
-
at 4mhz i think
so try to send it a pulse of 6 ms( 4 times 1.5ms) in your confused code. Once upon a time , I ran servo code at 8 mhz instead of the 4mhz which worked before. So all I did was double the 1.5 ms pulse , so the microcontroller though it was sending a 3ms pulse , but since it was at 8mhz it ended up giving 1.5 ms.
P.S. If you try to do the 6 ms pulse , have an on/off switch for the power supply , because if you leave it on and it gives a real 6ms pulse i think the servo will turn to the extreme angle and the gears will grind. or maybe the servo won't accept the pulse at all.
-
this just might work thanx.
-
well did it work?
-
nope, dont know what happened.....is it possible to loop through numbers and find the right milliseconds for stopping it
actually i think i was running it at 1mhz
-
how do you modify the delay_cycles code from atmega8 to atmega16
about the fcpu thing, i dont have it declared anywhere. shouldi declare it?
-
it looks like for any value 10ms and above the servo doesnt move, ignore this...it doesnt work
-
Wait . . . atmega16 or atmega168?
Anyway, you don't have to modify the delay code, its exactly the same.
What changes is the frequency you are running at . . . does your hardware have a crystal built in? Are you using the Arduino or the $50 Robot? What are your fuse frequency settings? Are you using AVRlib?
Here is a great way to determine your frequency for servo use (if you don't have an oscilloscope):
turn on LED
loop 10 times:
delay_cycles(65500);
turn off LED
loop 10 times:
delay_cycles(65500);
repeat
Now this means that 65500*10*2 cycles occur for every flash of the LED.
Now get out your watch and count the number of times your LED turns on in one minute.
Lets say its 30 times, count.
That means:
65500*10*2*count/(60 seconds) = cycles per second
or
655000 cycles/second
but what you want is to know how many cycles it takes for 1.5ms - the servo control time . . .
so:
655 cycles/ms -> 655*1.5=982.5
so to get your servo to stop moving, you'd want to send a signal of 1.5ms long, or 982.5:
turn servo on
delay_cycles(982);
turn servo off
Your servo moving one direction would be 655*1 (for 1ms), and the other way is 655*2 (for 2ms).
-
i'll try this..
Thanx alot admin, you are still the best
-
thanks :)
I think Ill turn that last post into a tutorial . . . it saved me tons of timing frustration when I figured that out last summer . . .
-
that wont be a bad idea
-
-----i am using a 16mhz external crystal with an atmega168
-------built like the $50 Robot
fuse frequency settings= i got this from sparkfun
----avrdude -p m168 -P com1 -c ponyser -U lfuse:w:0xE6:m
i am using AVRlib?
admin, one question:
loop 10 times:
turn on
loop 10 times:
turn off
do you mean i should run it in a for loop like
for (j = 0; j < 10; j++)
{
PORTC = 0xFF;
PORTB = 0xFF;
PORTD = 0xFF;
delay_cycles(65500);
PORTC = 0x00;
PORTB = 0x00;
PORTD = 0x00;
loop 10 times:
delay_cycles(65500);
}
OR
for (j = 0; j < 10; j++)
{
PORTC = 0xFF;
PORTB = 0xFF;
PORTD = 0xFF;
}
for (j = 0; j < 10; j++)
{
delay_cycles(65500);
PORTC = 0x00;
PORTB = 0x00;
PORTD = 0x00;
delay_cycles(65500);
}
-
regarding the F_CPU thing nope i guess it isn't needed in your case, i think you're not using avrlibc. you can ignore the F_CPU thingy.
-
you want to do that first for loop you posted, but probably just for your LED pin . . . I'm also doing 16MHz on another AVR, so if you did your fuse settings properly, you will find your delay should be around ~800.
since its just a quickie test, I just do:
while(1)
{
LED_on();
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
LED_off();
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
delay_cycles(65500);
}
-
i got 521, with the code i wrote. i'll try what you wrote. and was this correct for a 16mhz external oscillator
avrdude -p m168 -P com1 -c ponyser -U lfuse:w:0xE6:m
-
maybe i didnt do the fuse settings right, how can i do it right
-
Read Osc.Calibration Byte successful: 0xA8 (168)
i got 22 counts
i checked my fuse bits and they are correct
* CKDIV8 = 1
* CKOUT = 1
* SUT1 = 1
* SUT0 = 0
* CKSEL3 = 0
* CKSEL2 = 1
* CKSEL1 = 1
* CKSEL0 = 0
-
maybe i didnt do the fuse settings right, how can i do it right
I use AVR Studio to do my fuse settings.
i checked my fuse bits and they are correct
* CKDIV8 = 1
* CKOUT = 1
* SUT1 = 1
* SUT0 = 0
* CKSEL3 = 0
* CKSEL2 = 1
* CKSEL1 = 1
* CKSEL0 = 0
how do you know thats correct? are you sure you want to divide the clock by 8 (making it 1/8th the speed)? ;)
-
actually, i got that from sparkfun. I am using the serial dongle and thats what i saw on sparkfun's tutorial. well i just skimmed through the tutorial, maybe i missed something. I dont know how to do it with AVR though. If you could help me out that would be great.
-
nevermind about what I said earlier about the fuses, having a 0 makes it divide by 8 . . . oops . . .
anyway, if you have the serial dongle, you can't use AVR Studio to do the fuses . . . I'm guessing you are using ponyprog, right?
try the delay code yet?
-
-----i am using a 16mhz external crystal with an atmega168
-------built like the $50 Robot
fuse frequency settings= i got this from sparkfun
----avrdude -p m168 -P com1 -c ponyser -U lfuse:w:0xE6:m
i am using AVRlib?
you're using avrlibc? are you sure? AVRlibc is a small C library comparable to glibc. glibc is used in full-blown Linux systems mainly while AVRlibc is designed specifically for use with the Atmel AVR series of MCUs.
if you are using AVRlibc, your code and/or Makefile must have F_CPU defined. verify that all values match before recompiling.
whose code are you using? if you're using the $50 Robot code, the F_CPU definitions are in a file named global.h. find the file and select the F_CPU value that matches your setup.
-
i am using avrlib by procyon not avrlibc. FCPU is defined in the make file as 16mhz. maybe i did not set the fuse bits right. does anyone now how to set the fuse bits for an external 16mhz clock for an atmega168 with pony prog. i am using my own code based on the $50 robot but modified extensively
-
i also use procyon's libraries. procyon also uses F_CPU. it can also be defined in the Makefile or in the globals.h file.
make sure first that the correct F_CPU is not commented out. from one of my globals.h file:
// project/system dependent defines
// CPU clock speed
//#define F_CPU 20000000 // 20MHz processor
//#define F_CPU 16000000 // 16MHz processor
//#define F_CPU 14745000 // 14.745MHz processor
#define F_CPU 8000000 // 8MHz processor
//#define F_CPU 7372800 // 7.37MHz processor
//#define F_CPU 4000000 // 4MHz processor
//#define F_CPU 3686400 // 3.69MHz processor
#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond
yes you can see F_CPU as 16MHz but it is not used because it is commented out using C++ style comments. to enable the correct F_CPU value just remove the "//" in front of the definition.
#define F_CPU 16000000 // 16MHz processor
//#define F_CPU 14745000 // 14.745MHz processor
//#define F_CPU 8000000 // 8MHz processor
how did you connect your oscillator to the MCU? did you precisely follow the requirements/recommendations on page 31 and 32 of the ATmega168 data sheet? personally, the fuse settings that you are using seems to be correct based on the information that you have provided so far.
-
i did connect the oscillator right. i used two capacitors (22pf) connected to the oscillator to xtal pins.
-
i'am, at this point, all out of any constructive suggestions. the only thing i can suggest is to go and double, maybe even triple check your settings and setup.
-
ok, thanks for your help
-
solved it with PWM wooohooo.
// Servo test program
// Put your name here
// Put the date here
//----- Include Files ---------------------------------------------------------
#include <avr/io.h>
// include I/O definitions (port names, pin names, etc)
#include <avr/signal.h>
// include "signal" names (interrupt names)
#include <avr/interrupt.h>
// include interrupt support
#include "global.h"
// include our global settings
#include "timer.h"
// include timer function library (timing, PWM, etc)
#include "pulse.h"
// include pulse output support
#include "servo.h"
#include "iocompat.h"
int i;
// include RC servo support
//----- Function Declarations--------------------------------------------------
void init(void);
//----- Begin Code ------------------------------------------------------------
int main(void)
{
init();
// initialize everything
while(1)
{
for (i = 0; i < 255; i++)
{
servoSetPosition(0, i);
PORTD = 0x00;
timerPause(3000);
//servoSetPosition(0,0);
PORTD = 0xff;
timerPause(3000);
}
}
return 0;
}
// end main()
void init(void)
{
// initialize our libraries
timerInit();
// initialize the timer system
servoInit();
// initialize the servo system
// Setup I/O
DDRC = 0;
// Set PORTA to all inputs
PORTC = 0xff;
// Turn on pullup resistors
DDRD = 0xff; // Set PORTD to all outputs
PORTD = 0xff;
// Set PORTD outputs to high
}
// end init()
-
the code above works according to avrlib
-
I finally wrote that tutorial on calculating delay_cycles . . .
http://www.societyofrobots.com/microcontroller_time_cycles.shtml
-
Isn't it simpler:
http://mil.ufl.edu/~achamber/servoPWMfaq.html