ik heb een atmega16 met een 8 MHZ kristal.nou wou ik graag 1 of 2 servos aansluiten met drukknoppen. de hardware lukt wel de probleem wordt de software. het zou fijn zijn als iemand een leuke tutorial heeft of een komplete hex file 
(ik gebruik AVRstudio4 met AVRGCC)
bvd
mvg tolunay gul
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Zoals je wellicht weet, stuur je een servo aan door om de 20mS een puls te sturen die varieert tussen 1 en 2 mS. Voor het aansturen van 2 servo's kan je best 2 8-bits globale variabelen gebruiken, die je bij het initialiseren op 127 zet (middenstand servo).
Nu kan je bv. timer0 gebruiken om iets als dit te doen:
Wacht 9mS
Servo1 hoog
Wacht pulslengte servo1
Servo1 laag
Wacht 9mS
Servo2 hoog
Wacht pulslengte Servo2
Servo2 laag
Wacht 9mS enz...
De timer0 interrupt-handler kan aan de hand van een teller bijhouden in welke fase (1 ... 4) hij zich bevindt, en aan de hand daarvan zijn volgende wachttijd bepalen.
Het hoofdprogramma pollt de toetsen en past de pulslengte aan.
hoe een servo aangestuurd wordt weet ik wel
alleen de software zoals ik al zei, hier stond niks
de hardware is een eitje alleen de software.. pros... zou uw mij misschien kunnen helpen ?
[Bericht gewijzigd door tolunay op ]
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Hiermee ben je al een eind op weg, hoop ik:
#define F_CPU 8000000UL
// Wijzigen naar behoefte
#define SERVO1 PC6
#define SERVO2 PC7
#define SERVOPORT PORTC
#define SERVODDR DDRC
#define SERVO_MAX 2048
#define SERVO_MIN 1024
#define SERVO_PAUSE 10240
#define TOETSPORT PORTC
#define TOETSPIN PINC
#include <avr/interrupt.h>
#include <avr/io.h>
//#include <avr/sleep.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include <compat/deprecated.h>
volatile unsigned int servo1 = 1536, servo2 = 1536;
volatile unsigned char fase = 0;
// De timer1 interrupt-routine
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
switch (fase) {
case 0:
cbi(SERVOPORT, SERVO2); // Eind puls voor servo2
OCR1A = SERVO_PAUSE - servo2; // Wachttijd tussen servo-pulsen
break;
case 1:
sbi(SERVOPORT, SERVO1); // Begin puls voor servo1
OCR1A = servo1; // Wachttijd servo1-puls
break;
case 2:
cbi(SERVOPORT, SERVO1); // Eind puls voor servo1
OCR1A = SERVO_PAUSE - servo1; // Wachttijd tussen servo-pulsen
break;
case 3:
sbi(SERVOPORT, SERVO2); // Begin puls voor servo2
OCR1A = servo1; // Wachttijd servo2-puls
break;
default:
break;
}
fase++;
fase &= 0x03;
TCNT1 = 0; // Counter terug op 0 zetten
}
void init(void)
{
sbi(SERVODDR, SERVO1); // SERVO1 = uitgang
cbi(SERVOPORT, SERVO1); // die we onmiddelijk laag maken
sbi(SERVODDR, SERVO2); // Idem voor SERVO2
cbi(SERVOPORT, SERVO2);
TOETSPORT |= 0x0F; // Interne pull-ups inschakelen
TCCR1A = 0; // Timer1 in CTC-mode
TCNT1 = 0; // Counter op 0 zetten
OCR1A = SERVO_PAUSE; // Wachttijd tussen servo-pulsen
TIMSK |= _BV(OCIE1A); // Enable Timer1-interrupts
TCCR1B = _BV(CS11) | _BV(WGM12); // Gebruik de 256-prescaler
sei(); // Globale interrupt-vlag aan
}
int main(void)
{
unsigned char toetsen;
init();
while (1) {
switch (TOETSPIN & 0x0F) {
case 0x07:
servo1++;
if (servo1 > SERVO_MAX) {
servo1 = SERVO_MAX;
}
break;
case 0x0B:
servo1--;
if (servo1 < SERVO_MIN) {
servo1 = SERVO_MIN;
}
break;
case 0x0D:
servo2++;
if (servo2 > SERVO_MAX) {
servo2 = SERVO_MAX;
}
break;
case 0x0E:
servo2--;
if (servo2 < SERVO_MIN) {
servo2 = SERVO_MIN;
}
break;
default:
break;
}
_delay_ms(10);
}
}
Bij gebrek aan een ATmega16 heb ik maar een ATmega32 aan het werk gezet. Hopelijk zitten daar geen verschillen tussen, wat registers e.d. betreft.
Verder heb ik voor de 16-bits Timer1 gekozen, omdat 8 bits wel wat weinig is om de nodige vertragingen te bekomen. 't Is met Timer0 ook te doen, maar dan wordt het wat ingewikkelder.
waarom heb je niet de PWM functie gebruikt pros?
ik heb niet gerekend, want verwacht dat je er een goede reden voor hebt 
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Dat is ook een mogelijkheid, HmH. Misschien kan je tolunay een bruikbaar voorbeeld aan de hand doen, zodat hij kan kiezen?
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
De pulsen volgen mekaar op met een frequentie van 50Hz, en duren 1 tot 2 mS (wat me er aan doet denken dat er een flinke blunder in mijn code zit).
harstikke bedankt pros, dadelijk kan ik testen
volgens elektuur zit er geen verschil in de 16 en 32. allen geheugen verschil (16kb,32kb)
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
op welke pinnen moeten de knopjes ? ik zie dat de servos op port PC7 en PC6 moeten maar ik kan niet de knopjes zien 
ik heb hem zonder knopjes aangesloten maar hij werkt niet,tuurlijk de progje erin geladen.(pros zou je misschien jou hex file online kunnen zetten?
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Zonder toetsen zou hij pulsen van 1.5mS moeten geven, servo op neutrale stand, dus. De toetsen sluit je aan op PC0 ... PC3.
Hex-file staat op http://www.uploadarchief.net/files/download/servosturing.hex
[Update}
De oorzaak van je falen kan ik al raden: bij een nieuwe ATmega32 is JTAG geactiveerd; als dat bij de '16 ook zo is, kan je PORTC niet zo maar gebruiken. Oplossing: gebruik een andere poort en compileer opnieuw, of disable JTAG. En vergeen niet je fuses in te stellen voor een extern kristal!
[Bericht gewijzigd door pros op ]
pinky-t
Current project: "Bernaard the hexapod" (brother of alfred the hexapod).
hallo, ik heb dit topic even grondig doorgespit, opzoek naar het antwoord op mijn vraag, hoe stuur ik meerdere servo's aan met een atmega32.
ik heb het antwoord hier deels gevonden, en ben ook zeer dankbaar voor de beschikbaargestelde code, echter wil ik niet 2 servo's aansturen, maar bijvoorbeeld, 4 of 8 of 16, wat moet ik in de code veranderen zodat het werkt met servo1 t/m servo(X)
let even niet op het commentaar in de code, dat heb ik nog niet/nauwelijks gewijzigd, en lijkt dus nog grotendeels op het orgineel (bovenstaand gepost)
ik heb het volgende geprobeerd:
SERVO vervangen door POOT+NR
#define F_CPU 8000000UL
// Wijzigen naar behoefte
#define POOT1 PB1
#define POOT2 PB2
#define POOT3 PB3
#define POOT4 PB4
#define SERVOPORT PORTB
#define SERVODDR DDRB
#define SERVO_MAX 2048
#define SERVO_MIN 1024
#define SERVO_PAUSE 10240
#define TOETSPORT PORTA
#define TOETSPIN PINA
#include <avr/interrupt.h>
#include <avr/io.h>
//#include <avr/sleep.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include <compat/deprecated.h>
volatile unsigned int poot1 = 1536, poot2 = 1536, poot3 = 1536, poot4 = 1536;
volatile unsigned char fase = 0;
int x=0;
char keuze, keuze2;
// De timer1 interrupt-routine
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
switch (fase) {
case 0:
cbi(SERVOPORT, POOT2); // Eind puls voor servo2
OCR1A = SERVO_PAUSE - poot2; // Wachttijd tussen servo-pulsen
break;
case 1:
sbi(SERVOPORT, POOT1); // Begin puls voor servo1
OCR1A = poot1; // Wachttijd servo1-puls
break;
case 2:
cbi(SERVOPORT, POOT1); // Eind puls voor servo1
OCR1A = SERVO_PAUSE - poot1; // Wachttijd tussen servo-pulsen
break;
case 3:
sbi(SERVOPORT, POOT2); // Begin puls voor servo2
OCR1A = poot2; // Wachttijd servo2-puls
break;
case 4:
cbi(SERVOPORT, POOT4); // Eind puls voor servo2
OCR1A = SERVO_PAUSE - poot4; // Wachttijd tussen servo-pulsen
break;
case 5:
sbi(SERVOPORT, POOT3); // Begin puls voor servo1
OCR1A = poot3;
break;
case 6:
cbi(SERVOPORT, POOT3); // Eind puls voor servo1
OCR1A = SERVO_PAUSE - poot3; // Wachttijd tussen servo-pulsen
break;
case 7:
sbi(SERVOPORT, POOT4); // Begin puls voor servo2
OCR1A = poot4;
break;
default:
break;
}
fase++;
fase &= 0x07;
TCNT1 = 0; // Counter terug op 0 zetten
}
void init(void)
{
sbi(SERVODDR, POOT1); // SERVO1 = uitgang
cbi(SERVOPORT, POOT1); // die we onmiddelijk laag maken
sbi(SERVODDR, POOT2); // Idem voor SERVO2
cbi(SERVOPORT, POOT2);
sbi(SERVODDR, POOT3); // SERVO3 = uitgang
cbi(SERVOPORT, POOT3); // die we onmiddelijk laag maken
sbi(SERVODDR, POOT4); // Idem voor SERVO4
cbi(SERVOPORT, POOT4);
TOETSPORT |= 0x0F; // Interne pull-ups inschakelen
TCCR1A = 0; // Timer1 in CTC-mode
TCNT1 = 0; // Counter op 0 zetten
OCR1A = SERVO_PAUSE; // Wachttijd tussen servo-pulsen
TIMSK |= _BV(OCIE1A); // Enable Timer1-interrupts
TCCR1B = _BV(CS11) | _BV(WGM12); // Gebruik de 256-prescaler
sei(); // Globale interrupt-vlag aan
}
int main(void)
{
//unsigned char toetsen;
init();
}
zoals je kan zien heb ik getracht in timer1 interupt, extra cases toe te voegen, dit werkt niet. Dus als iemand me de juiste richting op sturen kan, of een stukje code aan kan passen zodat ik het begrijp. (Ik heb hier bewust de main weg gelaten, dat is verder niet zo interessant na ik dacht).
bijvoorbaat dank,
~ Bart