Bloccare servo in una posizione precisa

Sto scrivendo uno sketch che permetta ad arduino di ricevere i segnali con un ricevitore infrarossi e, in base al tipo di segnale, muovere il servo in una determinata posizione.

Al momento, riesco a muoverlo come voglio solo che non riesco a bloccarlo nel senso che dopo il primo comando ed il primo posizionamento, il servo continua a far rumore come se cercasse di far qualcosa anche se apparentemente resta fermo.
Credo sia colpa del mondo in cui gli passo la posizione.

Quello che dovrebbe fare è, settata la posizione a zero, muoversi a destra di 90 gradi e ritornare nella posizione originaria non appena termina il segnale di comando; allo stesso modo, dovrebbe ruotare di -90 gradi rispetto alla posizione originaria quando riceve un altro comando e ritornare a zero non appena non riceve più nulla.

Per esempio, se gli invio il comando “destra” lui deve ruotare di 90 gradi a destra e non appena smette di ricercare il segnale deve ritornare alla posizione di riposo e fare la stessa cosa col comando “sinistra”.

Potreste darmi dei consigli su come risolvere il problema e rendere il servo più reattivo e soprattutto più preciso?
Al momento non ritorna nemmeno alla posizione originaria una volta terminato il segnale.

Pensavo bastasse fissare pos = 0 e poi passargli myservo.write(90); e myservo.write(-90); ma evidentemente non funziona così.

Il circuito di invio dei segnali è su un altro Arduino e segue questa politica:

Sino a quando la leva del joystick è a sinistra, invia sempre il segnale infrarossi.

// spezzone di codice di esempio per il circuito di trasmissione
void loop{
 if (xAxis < 4 ) {
 button = Right; 
 irsend.sendSony(0xa91, 12); // Sony TV power code
 }
}

Mentre questo è il codice che riceve e muove il servo e su cui mi servirebbe aiuto:

int pos = 0;
// altro codice per inizializzare altre variabili
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); 
  myservo.attach(2);
 
}void loop() {
    digitalWrite(motor, HIGH);
    if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    
    if(results.value == 0xa91){
    Serial.println("RIGHT");
                                
    myservo.write(180);              
    delay(15);                       
    }
    if(results.value == 0xa92){
    Serial.println("LEFT");                              
    myservo.write(0);              
    delay(15);                        

    }
}

[quote author=marcus barnet link=topic=94829.msg712236#msg712236 date=1330793274] Pensavo bastasse fissare pos = 0 e poi passargli myservo.write(90); e myservo.write(-90); ma evidentemente non funziona così. [/quote]

L'oggetto servo accetta valori compresi tra 0 e 180, non accetta valori negativi, per posizionarlo al centro devi dare 90 mentre per portarlo agli estremi 0 o 180. Devi anche tenere in considerazione che non tutti i servo possono ruotare di 180*, che la posizione centrale non è uguale per tutti i modelli e i produttori, che la variazione del PPM in funzione dell'escursione cambia da modello a modello. Per farla breve per ottenere movimenti precisi devi fare delle prove per determinare il valore per metterlo al centro, che non sarà mai 90 ma un valore leggermente diverso, e i valori minimi e massimi per ottenere la totale escursione meccanica ammessa.

Se a destra corrisponde 0 e a sinistra corrisponde 180, suppongo che 90 sia la posizione di "attesa". Non so cosa tu debba fare però ti consiglio di aumentare il delay per dare il tempo al servo di mettersi in posizione, poi fuori dagli IF potresti mettere il servo a 90

Praticamente ho un joypad a due assi collegato ad un Arduino con un LED infrarossi che invia segnali ad un altro Arduino che ha un servo ed un ricevitore infrarossi.

Il servo simula il movimento della sterzata delle ruote anteriori, quindi quando lo stick del joystick è a destra, il servo deve ruotare di 90 gradi a dx e quando è a sinistra deve ruotare a 90 gradi a sx mentre appena lo stick ritorna nella posizione di riposo il servo dovrebbe ritornare anche lui nella posizione di attesa però al momento non funziona benissimo.

Forse perchè il servo non viene riposizionato correttamente e forse perchè nell'if() il codice tenta di posizionare più volte il servo a 180°,ad esempio, perchè continua a ricevere lo stesso segnale. Forse ho sbagliato lo logica di controllo e di ricezione dei segnali.

Che ne pensate?

Secondo me dovresti fare una cosa così:

   digitalWrite(motor, HIGH);
   
   if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    
    if(results.value == 0xa91){
     Serial.println("RIGHT");                            
     myservo.write(180);                                    
    }
    if(results.value == 0xa92){
     Serial.println("LEFT");                              
     myservo.write(0);                                   
    }
    myservo.write(0);

Cioè togliere i delay in modo che agisca in tempo reale, così quando lo stick torna a 0, il servo torna a 90. Comunque dipende anche dalla logica di trasmissione. Questo metodo dovrebbe andare bene, se non ho capito male..

sciorty: poi fuori dagli IF potresti mettere il servo a 90

C'è chi si diverte cosi'... :P

Johnny779:

sciorty: poi fuori dagli IF potresti mettere il servo a 90

C'è chi si diverte cosi'... :P

ahahah me n'ero accorto però l'ho lasciata così la frase, in attesa di un simile commento :D

sciorty:

Johnny779:

sciorty: poi fuori dagli IF potresti mettere il servo a 90

C'è chi si diverte cosi'... :P

ahahah me n'ero accorto però l'ho lasciata così la frase, in attesa di un simile commento :D

Diciamo che me l'hai servita su un piatto d'argento... :)

C'era una targhetta attaccata "Basta solo dirla!" (cit.) ;)

Probabilmente sono stupido, ma non riesco a capire cosa faccia il mio servo.

Ho lasciato per un momento il codice più elaborato di prima e sto provando le varie posizioni del servo con dei semplici comandi.

void setup() 
{ 
  Serial.begin(9600);
  myservo.attach(2);  
 myservo.write(90); // per posizionarlo al centro, non so se è corretto
} 
void loop() 
{ 
    delay(4000);  
    Serial.println("90");                              
    myservo.write(90);              
    delay(4000);                       
     Serial.println("0");                      
    myservo.write(0);
    delay(4000); 
    Serial.println("180");  
    myservo.write(180);
    delay(2000);  
}

Il problema è che il servo inizia a fare due rotazioni complete di 360 gradi prima in un verso e poi nell'altro e poi si ferma.

Io mi aspettavo che andasse prima a 90 gradi, poi si fermasse, e poi raggiungesse 180 gradi. Invece continua a girare come se fosse un ventilatore :)

Se invece uso lo sketch di esempio della libreria servo (sweep) che posiziona il servo tramite un ciclo for e incrementi di una unità, funziona bene.

Cosa sbaglio? :(

Allora dovresti avere un servo a rotazione continua, magari posta il nome per conferma. Forse funge da normale servo quando carichi lo sweep perchè in quel caso gli arrivano continuamente dei valori e non ha il tempo di fare il giro completo.

Però aspetta conferma perché non ho mai usato uno di questi servi, spero di aver azzeccato :D

Il servo è questo: Servocomando Hitec HS-55 L'ho preso da robot-italy: http://www.robot-italy.com/product_info.php?products_id=1830

C'è scritto che è a rotazione continua, quindi io non so aiutarti. Però mi è parso di capire da precedenti discussioni che a questi servi puoi solo dirgli di ruotare a destra, sinistra e fermarsi rispettivamente con i valori 0-90-180 (ipotesi).

Quindi attendi nuovamente conferma :)

Da quello che ho visto anche io dagli ultimi documenti che ho letto, mi sa che hai proprio ragione! Posso dirgli solo la direzione in cui girare.

Dato che sto per fare un nuovo ordine da robot-italy, qualcuno potrebbe consigliarmi un servo da prendere che non sia a rotazione continua, per favore? :(

Praticamente, al momento, riesco a muovere il servo ed a riposizionarlo non appena termino di inviare il segnale, quindi, diciamo che per funzionare funziona. Il problema è che se gli dico di ruotare verso destra e continuo a inviare lo stesso segnale dato che lascio premuta la leva del joypad a destra, il servo si posiziona correttamente ma continua ad oscillare di mezzo grado a sinistra ed a destra rispetto alla posizione in cui dovrebbe stare, quindi, non è stabile. Non capisco se è perchè il servo è a rotazione continua o se è per via di qualche errore nel codice che ho scritto.

void loop() {
  
    if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    
    if(results.value == 0xa91){
    Serial.println("RIGHT");
    myservo.write(80);             
    }                     
   
    
    if(results.value == 0xa92){
    Serial.println("LEFT");                              
    myservo.write(10);             
                         

    }
    if(results.value == 0xa93){
    Serial.println("DOWN");                              
   
    }
    if(results.value == 0xa94){
    Serial.println("UP");
   
   
    }
    if(results.value == 0xa95){
    Serial.println("UP-RIGHT");                              
    myservo.write(80);              // tell servo to go to position in variable 'pos' 
                         // waits 15ms for the servo to reach the position 

    }
    if(results.value == 0xa96){
    Serial.println("UP-LEFT");                              
    myservo.write(10);              // tell servo to go to position in variable 'pos' 
                         // waits 15ms for the servo to reach the position 

    }
        if(results.value == 0xa97){
    Serial.println("DOWN-RIGHT");                              
    myservo.write(80);              // tell servo to go to position in variable 'pos' 
  
    }
    if(results.value == 0xa98){
    Serial.println("DOWN-LEFT");                              
    myservo.write(10);              // tell servo to go to position in variable 'pos' 
   

    }
    dump(&results);
    irrecv.resume(); // Receive the next value
     myservo.write(40); // fa ritornare il servo ad una posizione di "riposo" non appena termina l'invio dei segnali di rotazione
  }
}

Ce ne sono molti, devi vedere quanti kg supportano, gli ampere e i volt di lavoro. L'uscita 5v della scheda Arduino mi pare che dia massimo 500 mA ma io ci starei sotto. Poi se devi fare cose particolari li puoi sempre alimentare esternamente.

Ma secondo te è sicuramente un servo di tipo rotativo continuo? perchè ho riguardato la descrizione e non ho trovato alcun riferimento.. :~

Cavolo ho sbagliato! Al posto di “Il servo Hitec HS-55 continua[…]” avevo letto “Il servo Hitec HS-55 a rotazione continua[…]”.
Comunque hai ragione, non dice nulla, però se il tuo servo gira in continuazione come se fosse un motore o l’hai modificato o è un servo a rotazione continua.

giralo a mano. se fa in tutto mezzo giro circa e si blocca(da entrambi i lati) è un servo normale, se non si blocca è a rotazione continua. allora non puoi usarlo assolutamente per il tuo scopo.
Se hai un negozio di modellismo dalle tue parti fai prima, tanto i prezzi stanno li…

vedendo qui sembra normale. http://www.servocity.com/html/hs-55_sub-micro.html
nel disegno ci sono anche i tempi di impulso per i gradi, quindi con la libreria servo puoi ‘accordarlo’ precisamente…

Ho provato e se lo giro a mano fa tutto il giro senza fermarsi sia in un senso che nell'altro.

Al momento, comunque, sono riuscito a farlo funzionare come volevo, però, preferirei utilizzare un servo che funziona correttamente in relazione a quello che voglio fare.

Purtroppo non ho un negozio di modellismo in zona, me ne consigliate uno da robot-italy, per favore? Li ho visti quasi tutti e non c'è scritto se sono a rotazione continua o meno a parte alcuni modelli che riportano espressamente la dicitura: "a rotazione continua".