Ik heb op ebay een aantal micro servo's gekocht en wil deze gaan aansturen met een atmega32 microcontroller. Ik heb een aantal tutorials gelezen hoe dat moet maar tot nu toe is het me nog niet gelukt.
Dit is wat ik weet over de servo
Name: micro servo 9g SG90
Dead band width: 7usec
Operating voltage: 3.0V~7.2V
Hij lijkt heel veel op de TowerPro sg90 maar is niet precies hetzelfde

Ik heb het volgende programmatje gemaakt:


int main(void)
{
unsigned int ontime = 2000;
init_devices();

while (1)
{
PORTD = PORTD & ~0x04; // on

_delay_us(ontime);

PORTD = PORTD | 0x04; // of

_delay_us(7);

if (!(PIND & 0x80))
{
if (ontime > 1)
ontime -= 1;

showOntime(ontime);
}

if (!(PIND & 0x40))
{
if (ontime < 4000)
ontime += 10;

showOntime(ontime);
}
}
}

De servo blijft in een maximale stand staan, als ik op de knopjes druk gebeurd er niks maar als ik een van de knoppen inhoud gaat hij langzaam naar het andere uiteinde. Als ik de knop weer loslaat gaat hij weer langzaam terug.

Werkt het om op deze manier de servo aan te sturen(om te testen) en wat doe ik dan fout?

Bij het sturen van een servo moet je om de 20mS een positieve puls geven, waarvan de breedte varieert tussen 1 en 2mS. Je kan dat softwarematig gaan implementeren, maar dat loopt mooi in 't honderd zodra je gebruik maakt van interrupts, die je tijdschema verknoeien.
Gebruik een PWM-kanaal. Eens dat goed ingesteld is, kan je main() zich met andere zaken bezighouden...

Een voorbeeld kan je hier vinden.

ja ik snap dat het op deze manier niet goed gaat maar dit was voor het testen hoe lang die pulsen moeten zijn. Ik dacht omdat er stond "dead band with: 7usec" dat ik 7 micro seconden geen signaal moet sturen en dan die 1-2 ms zoals ik dus doe in mijn programma.

Ik heb het geprobeerd met het programmatje wat ik poste met de tijden 20 ms uit en 1-2 ms aan maar dan doet de servo helemaal niks.

Die "dead band width" geeft de periode aan, waarbij de servo niet reageert op veranderingen in de pulslengte. Als die bv, varieert tussen 1500 en 1507µSec, dan zal de servo dat negeren.
Verder lijkt het mij een gewone servo. Je hebt hem toch goed aangesloten? Zwart = GND; rood = +5V; geel = puls.

ja hij zit goed aangesloten, alleen is het bij mij wit en niet geel maar dat maakt volgensmij niet veel uit.

Wat ik wel zag is dat ik F_CPU niet had gedefinieert, delay.h maar nu ik deze wel heb maakt het ook geen verschil.

Verder heb ik nog een andere servo geprobeerd omdat ik deze misschien verknalt heb. Hij werdt na wat prutsen heeel warm omdat hij heel veel aan het bijstellen was. Maar dat maakte ook geen verschil.

hier mijn hele code, doe ik iets anders fout?


#include "servo.h"
#include "lcd/lcd.h"

#include <stdlib.h>
#include <interrupt.h>
#define F_CPU 8000000
#include <util/delay.h>


//Hoofdprogramma
int main(void)
{
	unsigned int ontime = 1500;
	init_devices(); 

	while (1)
	{
		PORTD = PORTD & ~0x04;	// aan

		_delay_us(ontime);

		PORTD = PORTD | 0x04;	// uit

		_delay_ms(20);

		if (!(PIND & 0x80))
		{
			if (ontime > 10)
				ontime -= 10;

			showTime(ontime);
		}

		if (!(PIND & 0x40))
		{
			if (ontime < 4000)
				ontime += 10;

			showTime(ontime);
		}
	}

}

//Functies
void init_devices (void)
{
	cli ();	   			// Disable global interrupts

	port_init ();		// Roep de functie om de poorten te initializeren aan

	lcd_init(LCD_DISP_ON);
	lcd_clrscr();
}

void port_init (void)
{

	PORTD = 0xFF;	// Pull-ups disabled
 	DDRD  = 0x0F; 	//
}

void showTime(unsigned int ontime)
{
	char buf[10];

	lcd_clrscr();
	lcd_puts("Ontime is: ");
	lcd_puts(utoa(ontime, buf, 10));
	lcd_puts("\n"); 
}

Verder heb ik eens naar pwm gekeken maar dat lukt nog niet helemaal, ik heb ook geen scope dus kan het niet makkelijk controleren wat voor een signaal ik nauw precies maak.


	unsigned int ontime = 1500;
//...
        _delay_us(ontime);

Da's twee maal fout.

Om te beginnen, is de maximale delay-time voor _delay_us() gelijk aan 768 us / F_CPU in MHz. Bij een systeemklok van 8MHz is dat 96.

Daar komt bij dat, als de delay-time bij het compileren niet gekend is ( _delay_us(ontime) ipv. _delay_us(50.25) ), de compiler daar een floating-point bewerking neerzet die de uiteindelijke firmware opblaast als gek.

Wat ik zelf doe, is enkele simpele routines opnemen in mijn broncode:


void delay_ms(unsigned int ms)
{
    for (; ms > 0; ms--) {
	_delay_ms(0.998);
    }
}


void delay_us(unsigned int us)
{
    for (; us > 0; us--) {
	_delay_us(0.95);
    }
}

Nu kan je zowel delay_us() als delay_ms() een waarde meegeven tot 65535.

dat was een fout en de andere heb ik zowaar zelf gevonden, dat niemand dat gecontroleerd heeft
ik heb het aanzetten en uitzetten omgedraaid... :P nu doet ie het goed!!! bedankt!
dan ga ik zo ook maar eens kijken hoe dat pwm werkt, ik zal wel weer een topic aanmaken als ik een vraag heb