May 04, 2009
by Dryak
|
I'm looking to create a simple program that loops making the servo turn from left to right, but I don't know what libraries include.
I've got a pretty good programming background, but I've never programmed hardware before so I don't know where the resources for servo libraries would be.
|
May 05, 2009
by DonNYC
|
Have a look at the Servo Squirter code.
|
May 06, 2009
by Dryak
|
Can someone explain the code to me? Its not exactly commented the best so I don't know what its doing.
|
July 28, 2009
by BoloBit64
|
the first part of the code void pwm_int is to setup the timing for the servo. All the definintions can be found in the AVR datasheet in Chapter 14. It explains how it changes the milliseconds to get a faster, 1 ms, or slower, 20 ms, reponse time. Next is int main. the first part is to tell the lcd what to display, in this case " Nerdkits ServoSquirter". then it connects the serial port, then it sets DDRB, Chapter 13.4 in AVR datasheet for specifics, pins 2 and 3 to control the direction of the servo. After that, its activates the PWM mode where the Displays the position of the PWM. Then, using the uart, set the bounderies of the servo. When you reach thoughs boundaries it sends the character to the serial port. the Next part checks the boundaries of the servo and makes sure it doesn't go to far. And the last bit of code sends the position to serial port. I hoped this helped anyone still wondering.
|
September 09, 2009
by Nerdful_com
|
Anyone have a basic sample code (no UART, no LCD, etc) that just moves a hobby servo to say 3 positions (like all the way left, all the right and centered)? Nerdful.com
|
October 07, 2009
by lcruz007
|
I wrote a simple program that will work like you want (the servo moves from left to right, in an infinite loop, but a 25 seconds loop is always repeating)... I will post it here in a separate post. Hope you find it helpful.
|
October 07, 2009
by lcruz007
|
#define F_CPU 14745600
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"
// PIN DEFINITIONS:
//
// PB3 - pump control
// PB2 - servo signal (OC1B)
void pwm_set(uint16_t x) {
OCR1B = x;
}
#define PWM_MIN 1300
#define PWM_MAX 4450
#define PWM_START 2875
void pwm_init() {
// setup Timer1 for Fast PWM mode, 16-bit
// COM1B1 -- for non-inverting output
// WGM13, WGM12, WGM11, WGM10 -- for Fast PWM with OCR1A as TOP value
// CS11 -- for CLK/8 prescaling
OCR1A = 36864; // sets PWM to repeat pulse every 20.0ms
pwm_set(PWM_START);
TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);
// each count is 8/14745600 = 0.5425us.
// so 1.0ms = 1843.2
// 1.5ms = 2764.8
// 2.0ms = 3686.4
// 20.0ms = 36864
}
/* CLOCK PURPOSES ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= */
void realtimeclock_setup() {
// setup Timer0:
// CTC (Clear Timer on Compare Match mode)
// TOP set by OCR0A register
TCCR0A |= (1<<WGM01);
// clocked from CLK/1024
// which is 14745600/1024, or 14400 increments per second
TCCR0B |= (1<<CS02) | (1<<CS00);
// set TOP to 143
// because it counts 0, 1, 2, ... 142, 143, 0, 1, 2 ...
// so 0 through 143 equals 144 events
OCR0A = 143;
// enable interrupt on compare event
// (14400 / 144 = 100 per second)
TIMSK0 |= (1<<OCIE0A);
}
// the_time will store the elapsed time
// in hundredths of a second.
// (100 = 1 second)
//
// note that this will overflow in approximately 248 days!
//
// This variable is marked "volatile" because it is modified
// by an interrupt handler. Without the "volatile" marking,
// the compiler might just assume that it doesn't change in
// the flow of any given function (if the compiler doesn't
// see any code in that function modifying it -- sounds
// reasonable, normally!).
//
// But with "volatile", it will always read it from memory
// instead of making that assumption.
volatile int32_t the_time;
SIGNAL(SIG_OUTPUT_COMPARE0A) {
// when Timer0 gets to its Output Compare value,
// one one-hundredth of a second has elapsed (0.01 seconds).
the_time++;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int Auto = 1; //Moves servo automatically
int main() {
//clock
realtimeclock_setup();
// init LCD
lcd_init();
FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
// lcd_write_string(PSTR(" NerdKits ServoSquirter "));
// init serial port
uart_init();
FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;
// turn on interrupt handler
sei();
// set PB2,PB3 as output
DDRB |= (1<<PB2) | (1<<PB3);
// init PWM
pwm_init();
uint16_t pos = PWM_START;
double ang = 90;
char tc;
int tr = 1;
int pump_stop = 0;
if( tr == 1 )
{
lcd_home();
lcd_line_one();
lcd_write_string(PSTR ("Automatic servo"));
delay_ms(3000);
lcd_clear_and_home();
lcd_write_string( PSTR ("*******************"));
lcd_line_two();
lcd_write_string(PSTR (" ROBO-SQUIRTER"));
lcd_line_three();
lcd_write_string(PSTR("*******************"));
delay_ms(3000);
lcd_clear_and_home();
the_time = 0;
tr=0;
}
while(1) {
pwm_set(pos);
// Print the current servo position to the LCD.
lcd_home();
fprintf_P(&lcd_stream, PSTR(" servo pos: %d "), pos);
lcd_line_two();
fprintf_P(&lcd_stream, PSTR(" Angle: %.2f"), ang);
lcd_write_data(0xdf);
if ( Auto == 1 ) //If the user chooses to move the servo automatically
{*/
lcd_line_three();
// fprintf_P(&lcd_stream, PSTR("%16.2f sec"), (double) the_time / 100.0);
// so 1.0ms = 1843.2
// 1.5ms = 2764.8
// 2.0ms = 3686.4
if( the_time >= 2600 )
the_time = 0;
if(pump_stop == 0)
PORTB |= (1<<PB3); //ENables pump
if(pump_stop == 1)
PORTB &= ~(1<<PB3); //Disables pump
if( the_time <= 500 ) //If the time is less than 5 seconds
{
if ( pos >= 1250 )
{
pos -= 25;
ang = 0.057142857 * (pos-1300);
}
pump_stop = 0;
}
if( the_time >= 500 && the_time <= 1000 )
{
if ( pos <= 4400 )
{
pos += 25;
ang = 0.057142857 * (pos-1300);
}
pump_stop = 0;
}
if( the_time >= 1000 && the_time <= 15000 )
{
pump_stop = 1; //Disables pump
}
if( the_time >= 1500 && the_time <= 2000 )
{
pump_stop = 0;
if ( pos >= 1250 )
{
pos -= 25;
ang = 0.057142857 * (pos-1300);
}
}
if( the_time >= 2000 && the_time <= 2500 )
{
pump_stop = 0;
if ( pos <= 4400 )
{
pos += 25;
ang = 0.057142857 * (pos-1300);
}
}
if( the_time >= 2500 )
{
ang = 0.057142857 * (pos-1300);
Auto = 0;
the_time = 0;
}
if( ang <= 0 )
{
ang = 0;
}
if( ang >= 190 )
{
ang = 0;
}
if( ang >= 180.1 && ang <= 185 )
{
ang = 180;
}
if( pos >= 3025 )
{
if( pos <= 3025 )
lcd_clear_and_home();
}
if( pos >= 1450 )
{
if( pos <= 1450 )
lcd_clear_and_home();
}
// Print the current servo position to the serial port.
// printf_P(PSTR("%d\r\n"), pos);
}
return 0;
}
|
January 13, 2010
by mongo
|
I just tried out a few things last night with the servo squirter project. The code was simple enough but boy did I have trouble getting anything out of it...
I copied and pasted the makefile from the traffic light project and edited it to the servo squirter filenames. A word to the wise... And the rest too - double check your spelling and typos. Next time, I am just going to use copy and replace globally.
At any rate, I did get it working. I had a couple of Futaba servos sitting in a box and once I got the program figured out, changing the variables and adding different parameters went pretty easily.
I added more keyboard characters for stepping in smaller increments as well as full sweep and center positions. Now I need to find a use for something like this. I am also looking ino adapting the setup for two servos. More on that when it happens.
Mongo
|