Ce week-end, j'ai commencé à tester mes servomoteurs avec plus ou moins de réussite.
J'ai donc commencé par un classique, la modul de largeur d'impulsion (pwm) et çà marche pas mal. Mais comme j'aimerais utiliser un attiny2313 comme controlleur, il faut que je puisse utiliser tous les pins disponibles, y compris les non-pwm.
Alors, j'ai cherché sur la toile et j'ai effectivement trouvé des choses, mais en assembleur, et c'est vite devenu pour moi indigeste
J'effectue mes essais avec 2 servos et un atmega328 (duemilanove). J'utilise pour contrôler mes servos le timer 1 en mode CTC afin de simuler les 50hz indispensables.
Le problème est que le second servo ne réagit pas du tout comme il faudrait (ne tourne que dans un sens avec des ratés de temps à autre, alors que le premier servo est ok) et j'ai l'impression qu'entre la commande (séquentielle) et la pulsation, j'ai un léger décalage temporel qui me fait sauter les pulsations suivantes.
Je pense être dans la bonne direction mais là je sèche sur la méthode pour résoudre ce problème. Un peu d'aide ferait du bien
la première devrait t'intéresser davantage, elle gère le 2313.
Par ailleurs avec ces versions, il faut utiliser "SerialServo" et plus la lib "servo" avec un rafraichissement tous les 40 ou 50 ms...
de gère un seul servo et ça a très bien fonctionné.
Bon ces lib ne gèrent que des servos 180° alors je sais pas si ça t'aidera vraiment.
Par simple curiosité:
tu les trouves où les servos à 360 ?
Ce sont des servos hackés pour faire un suiveur de lignes? (le servo sert de moteur?)
ok je connais alors... :*
je savais pas comment ça s'appelait
il faut ajuster les valeurs basses et hautes des valeurs d'attach pour avoir un stop à 90°.
merci.
Pour info, j'ai déjà joué avec des tiny2313 et je possède de longue date le core XD
Comme je n'arrive pas à avoir le résultat escompté avec le mode CTC, je suis retourné sous PWM pour valider mes essais.
J'arrive donc à piloter mes servos par ce biais. Par contre, je dois toujours avoir un problème de timing, les servos n'ont pas leur vitesse maxi et on entends les pulsations à l'oreille, c'est donc un peu beaucoup saccadé.
Et un nouveau code, un :
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile byte s;
volatile unsigned int servoPulse[8]={3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000};
void _init_();
void setup()
{
Serial.begin(19200);
_init_();
}
void loop()
{
if (Serial.available())
{
char value = Serial.read();
switch(value)
{
case 's' : stopPwm(); Serial.println("stop"); break;
case 'd' : startPwm(); Serial.println("start"); break;
case 'a' : servoPulse[0] = 1800; break; // fast
case 'z' : servoPulse[0] = 4200; break; // fast
case 'e' : servoPulse[0] = 3000; break; // stop
case 'f' : servoPulse[0] = 2750; break; // slow
case 'r' : servoPulse[0] = 3250; break; // slow
case 'w' : servoPulse[1] = 1800; break; // fast
case 'x' : servoPulse[1] = 4200; break; // fast
case 'c' : servoPulse[1] = 3000; break; // stop
case 'v' : servoPulse[1] = 2750; break; // slow
case 'b' : servoPulse[1] = 3250; break; // slow
default : break;
}
}
servoPulse[0] = 1800;
servoPulse[1] = 1800;
_delay_ms(1000);
servoPulse[0] = 3000;
servoPulse[1] = 2700;
_delay_ms(1000);
servoPulse[0] = 4100;
servoPulse[1] = 2000;
_delay_ms(1000);
}
void _init_()
{
cli();
TCCR1A = 0;
TCCR1B = 0;
DDRB |= B00000011; // PB0, PB1 = Servos
__asm__("nop\n\t");
TCCR1A = (1 << WGM11); // Fast PWM, non invert
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); // prescaler = 8
TIMSK1 |= ((1<<OCIE1A) | (1<<TOIE1));
TCNT1 = 0;
ICR1 = 39999; // ((16000000 / 50) / 8) - 1 = 40000 - 1
OCR1A = 3000; // center position (40000 x 1.5)/20 = 3000
sei();
}
ISR(TIMER1_COMPA_vect)
{
PORTB &= ~( 1 << s); //Turn off PBx
s++; //Increment Servo Channel
if (s > 7) s = 0;
OCR1A = servoPulse[s]; //Update PWM duty for next Servo
}
ISR(TIMER1_OVF_vect)
{
PORTB |= ( 1 << s); //Turn on Servo Channel (s)
}
void stopPwm()
{
TCCR1A = 0x0;
}
void startPwm()
{
TCCR1A = (1 << WGM11) | (1 << COM1A1);
}
En simplifiant ce code pour un seul servo, çà marche impec