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:
Fine Corsa Superiore premuto e Servo fermo (condizione di riposo)
Attivazione Rele e Servo con pulsante (ruotazione oraria)
Stop Servo quano arriva al Fine corsa Inferiore
Attesa x secondi
Ruotazione Servo in direzione contraria (antioraria)
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
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.
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 )?
@ 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.
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.
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."
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)?
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.
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.