Servo 360° e fine corsa [ Risolto]

Salve a tutti,
avrei bisogno del vostro aiuto per realizzare un progetto.

Ho un servo 360 gradi che vorrei potesse ruotare esattamente ( avanti ed indietro) di un certo angolo.

Non potendolo comandare in gradi ma in "Microseconds " non riesco ad ottenere la precisione di cui ho bisogno per cui avrei pensato di mettere 2 fine corsa.

Qui viene il problema perchè ho diverse condizioni che devo rispettare e sono riuscito a farle alcune
ma non riesco ad implementarle tutte insieme.

In poche parole il funzionamento a blocchi dovrebbe essere questo:

  1. Fine Corsa Superiore premuto e Servo fermo (condizione di riposo)
  2. Attivazione Rele e Servo con pulsante (ruotazione oraria)
  3. Stop Servo quano arriva al Fine corsa Inferiore
  4. Attesa x secondi
  5. Ruotazione Servo in direzione contraria (antioraria)
  6. Stop Servo e Relè quano arriva al Fine corsa Superiore

Metto qui sotto il codice che funziona senza i finecorsa, ma come detto gestendo i tempi non torna mai nella posizione iniziale

#include <Servo.h> 
Servo myservo;                  // Servo 360°

# define TASTO 7                // Collegare Pin 7 a GND per attivare relè 
# define RELE  8                // PIN di Uscita per Comando Relé
# define SUP 10                 // Ingresso Fine Corsa Superiore
# define INF 11                 // Ingresso Fine Corsa Inferiore

int a = 0;
int b = 0;
int c = 0;


void setup() 
{ 
  myservo.attach(9); // PIN che comanda il servo
  
  pinMode(RELE, OUTPUT);      
  
  pinMode(TASTO, INPUT);     // Pulsante per attivazione ciclo
  digitalWrite(TASTO, HIGH);// Resistenza Pull-Up
  
  pinMode(SUP, INPUT);    // Finecorsa Superiore 
  digitalWrite(SUP, HIGH);// Resistenza Pull-Up
  
  pinMode(INF, INPUT);    // Finecorsa Inferiore 
  digitalWrite(INF, HIGH);// Resistenza Pull-Up
 
  Serial.begin(9600);
}

void loop(){

Serial.print(a);
Serial.print(b);
Serial.println(c);

  if (digitalRead(TASTO) == LOW){
     a = 1; 
    }
   else {
     a = 0;
     digitalWrite(RELE, HIGH); // Se non è premuto il tasto tiene il comando del Relè
    }                                     // ALTO e quindi il Relè è DISATTIVATO
     
  if (digitalRead(INF) == LOW){
    b = 1; 
    }
  else {
    b = 0;
    }  
   
  if (digitalRead(SUP) == LOW){
    c = 1;  
    }
   else {
    c = 0;
    }
   
  
                            
                                

if(a == 1){

  digitalWrite(RELE, LOW); // Attivo il rele portando l'uscita BASSA
    
  myservo.writeMicroseconds(2000);  // Gira in senso orario
  delay(1000);
  myservo.writeMicroseconds(1500);  // Ferma Servo
  delay(2000);
  myservo.writeMicroseconds(1000);  // Gira in senso Antiorario
  delay(1000);
  myservo.writeMicroseconds(1500);  // Ferma Servo
  delay(2000);
 
 } 
  
 }

Sicuramente mi sto perdendo in un bicchiere d’acqua, ma se qualcono potesse darmi qualche “dritta”
gli sarei davvero grato :slight_smile:

Quale Servo hai (modello)?

Spesso 360° é inteso che il servo é modificato e non ha un finecorsa ne una posizione che corrisponde al pilotaggio. Questi Servo sono usati nei piccoli robot come motori per ile ruote e sono pilotabili per un moto in avanti e indietro.

Ciao Uwe

Ciao, grazie per la risposta.

No propio un servo 360° originale non uno modificato, per l'esattezza LF-20MG (20Kg)

Non esistono servo 360° originali, infatti il tuo modello è un normale servo cineseria ad uso sterzo su auto rc fuori strada, un servo decente di quel tipo costa non meno di 60 E. Quando i servo vengono venduti come 360° vuol dire che sono stati modificati dal venditore per ottenere questa modalità, anomala, di funzionamento, in pratica viene rimosso il blocco meccanico alla rotazione del servo, tipicamente circa 180°, viene scollegato, o rimosso, il potenziometro che rileva la posizione dell'asse in uscita e al suo posto viene montato un partitore resistivo, a volte un trimmer, che ne simula il valore equivalente a 0°. In pratica un servo a 360° altro non è che un motoriduttore dotato di elettronica di controllo integrata, però come resistenza meccanica ai carichi radiali è di gran lunga minore di un vero motoriduttore equivalente come potenza e velocità, il controllo della velocità è una cosa molto aleatoria in quanto in basta spostarsi di poco dal punto centrale per far girare il servo sempre alla massima velocità, inoltre i servo a 360° hanno una vita molto breve perché, dal punto di vista meccanico ed elettrico, non sono progettati per girare in continuazione. Per farla breve, i servo a 360° vanno bene solo per motorizzare piccoli robot, max 500-600 grammi di peso, senza troppe pretese di precisione. Per il tuo uso era molto meglio se prendevi la versione non modificata visto che così avevi un "preciso" controllo sulla posizione, nel tuo caso scordati di ottenere posizionamenti precisi usando il tempo come entità di controllo in quanto la velocità di rotazione non è una costante, il solo modo è l'uso di due fine corsa se ti servono solo due posizioni.

Ma non capisco bene lo stesso, per cui vorrei capire (e chiedo a chi è più esperto di me). Se ha due fine corsa magari a 180 gradi o meno, non gli serve un servo a rotazione continua ma uno normale da 180 gradi. Se i fine corsa sono a più di 180 gradi allora potrebbe andare, ma credo possa bastare usare quei sensori per fare una calibratura iniziale, e da questa capire cosa mandare al servo in base all'angolo desiderato. Oppure montare un trimmer solidale con l'asse e usarlo come sensore di posizione (in questo caso non serve neanche un servo, basta uno stepper). cosa che ho fatto io con un braccio robotico (modificando un normale braccio filoguidato, non un kit apposito, mi volevo divertire ;) ).

Sbaglio o trascuro qualcosa? Consigli per la migliore soluzione ad un problema simile (ma senza spendere per motori costosi ;) )?

Altra curiosità, perché hai messo:

pinMode(TASTO, INPUT); // Pulsante per attivazione ciclo digitalWrite(TASTO, HIGH);// Resistenza Pull-Up

invece di "pinMode(TASTO, INPUT_PULLUP);"?

@ astrobed(cit) " il solo modo è l'uso di due fine corsa se ti servono solo due posizioni."

E' esattamente quello che ho scritto, infatti la mia richiesta di aiuto era per capire come potevo implementare lo sketch sopra riportato con l'aggiunta di 2 finecorsa.

@docdoc

Rispondo alle tue curiosità: 1) Ho in casa questo Servo ed in ogni caso il movimento deve essere più di 180° gradi e non posso mettere uno stepper per via dell'ingombro.

2) Non mi vorrei sbagliare ma l'istruzione " INPUT_PULLUP" non credo funzioni con IDE 1.0.6 che uso.

Roby0303:

  1. Ho in casa questo Servo ed in ogni caso il movimento deve essere più di 180° gradi e non posso mettere uno stepper per via dell’ingombro.

Hm, capito, quindi neanche un riduttore meccanico 1:2 immagino.
Secondo me ti semplifichi la vita se provi dei servo multigiro con feedback come questo HS-785HB per barche a vela. Costicchia rispetto agli altri “normali” ma hai un servo con feedback e ben 2826 gradi di rotazione.

  1. Non mi vorrei sbagliare ma l’istruzione " INPUT_PULLUP" non credo funzioni con IDE 1.0.6 che uso.

:o

Comunque nel reference leggo: “As of Arduino 1.0.1, it is possible to enable the internal pullup resistors with the mode INPUT_PULLUP.

Roby0303: Non mi vorrei sbagliare ma l'istruzione " INPUT_PULLUP" non credo funzioni con IDE 1.0.6 che uso.

Deve funzionare, sempre usata !

Guglielmo

Tra l'altro ho anche dubbio che mandando HIGH un pin definito INPUT attivi il pullup interno, ma semplicemente che metta HIGH quella porta se non connessa a nulla (alta impedenza), poi sicuramente andrà LOW se collegata a GND (ad esempio con un pulsante verso massa) ma se ridisconnessa (quindi lasciata flottare) secondo me non torna HIGH. O no?

docdoc: Tra l'altro ho anche dubbio che mandando HIGH un pin definito INPUT attivi il pullup interno,

Se fai una digitalwrite ad High su un pin definito come input attivi la pullup interna, è una caratteristica hardware degli AVR, non dipende dal software. Il parameto input_pullup nella pinmode non fa altro che settare ad high il relativo pin di input attivando la pullup, in pratica risparmia la "fatica" di dover fare una digitalwrite dopo la pinmode come input.

Grazie del chiarimento! Non conosco ancora la struttura interna AVR ma (mi piace cercare di capire) immagino che probabilmente "scrive" nel buffer di quel GPIO un valore HIGH per cui quando l'ingresso è ad alta impedenza continua a leggere questo, oppure è proprio nell'hardware che si attiva mandando HIGH un pin input? O entrambe (nel senso che l'INPUT_PULLUP funziona facendo proprio questo)?

Basta che prendi il datasheet e guardi come sono fatti i pin di I/O ... pagina 93 ...

... come vedi, in alto a sinistra, c'è proprio un MOSFET dedicato ad attivare la pull-up controllato dal segnale PUD e da un altro paio di segnali. :wink:

Guglielmo

Ritornando al mio problema potete aiutarmi a capire come gestire i fine corsa con quel servo che ho?

il problema maggiore lo sto trovando nel dover implementare il fermo e ritorno alla posizione iniziale del servo quando viene premuto il fine corsa che ho chiamato inferiore.

Grazie a chiunque possa farlo :)

Beh direi inizia a modificare il tuo programma per introdurre i sensori di fine corsa (es. per i pin dove li metterai, a cosa corrispondono..), poi postalo qui anche se non funziona così partiamo da qualcosa che sicuramente possiamo provare e tu verificare.

Allora, finalmente sono riuscito a far funzionare lo sketch come volevo, integrando i 2 fine corsa.

Sono sicuro che si potrebbe fare meglio , ma come si dice…l’importante è che funzioni :slight_smile:

In ogni caso lo metto qui sotto casomai a qualcuno serva

#include <Servo.h> 
Servo myservo;                  // Servo 360°

# define TASTO 7                // Collegare Pin 7 a GND per attivare relè 
# define RELE  8                // PIN di Uscita per Comando Relé
# define SUP 10                 // Ingresso Fine Corsa Superiore
# define INF 11                 // Ingresso Fine Corsa Inferiore

int a = 0;
int b = 0;
int c = 0;

boolean movimento_orario = false;
boolean movimento_antiorario = false;
boolean ritorno = false;
boolean riposo = false;

void setup() 
{ 
  myservo.attach(9); // PIN che comanda il servo
  
  pinMode(RELE, OUTPUT);      
  
  pinMode(TASTO, INPUT);     // Pulsante per attivazione ciclo
  digitalWrite(TASTO, HIGH);// Resistenza Pull-Up
  
  pinMode(SUP, INPUT);    // Finecorsa Superiore 
  digitalWrite(SUP, HIGH);// Resistenza Pull-Up
  
  pinMode(INF, INPUT);    // Finecorsa Inferiore 
  digitalWrite(INF, HIGH);// Resistenza Pull-Up
 
  Serial.begin(9600);
}

void loop(){

Serial.print(movimento_orario);
Serial.print(movimento_antiorario);
Serial.print(a);
Serial.print(b);
Serial.println(c);

  if (digitalRead(TASTO) == LOW){   
     a = 1; 
    }
   else {
     a = 0;
     digitalWrite(RELE, HIGH);     // Relè è DISATTIVATO
    }                          
     
  if (digitalRead(INF) == LOW){
    b = 1; 
    }
  else {
    b = 0;
    }  
   
  if (digitalRead(SUP) == LOW){
    c = 1;  
    }
   else {
    c = 0;
    }
   
  
                            
  // Movimento ORARIO                              

  if(a == 1 ){
    movimento_orario= true;
    } 
  
  if(movimento_orario == true ){
  
   digitalWrite(RELE, LOW); // Attivo il relé 
   
  myservo.writeMicroseconds(1800);  // Gira in senso orario
  
    }
  // Fermo e Pausa Servo
  
  if(b == 1 && ritorno == false){
    myservo.writeMicroseconds(1500);  // Ferma Servo
    delay(2000);
    movimento_orario= false;
    ritorno = true;
    
    } 

   // Movimento ANTIORARIO e Posizione di Riposo
   
   if(ritorno == true ){
    digitalWrite(RELE, LOW); // Attivo il relé 
    myservo.writeMicroseconds(1300);  // Gira in senso Antiorario
    movimento_antiorario= true;
    
    
    if (c == 1){
     myservo.writeMicroseconds(1500);  // Ferma Servo
     delay(1000);
     digitalWrite(RELE, HIGH);         // Disattivo relé
     a=0;
     b=0;
     c=0;
     movimento_antiorario= false;
     movimento_orario= false;
     ritorno=false;
        
     } 
   }                     
}

Roby0303: Se devo aprire un'altro post per questa nuova richiesta o devo modificare il titolo di questa ( se si può fare) lo faccio.

Il titolo si corregge sempicemente editando il PRIMO post di un thread e modificandolo. ;)

Guglielmo